feat(web)!: SPA (#5069)
* feat(web): SPA * chore: remove unnecessary prune * feat(web): merge with immich-server * Correct method name * fix: bugs, docs, workflows, etc. * chore: keep dockerignore for dev * chore: remove license * fix: expose 2283 --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
+3
-3
@@ -1,4 +1,4 @@
|
||||
node_modules/
|
||||
upload/
|
||||
dist/
|
||||
|
||||
coverage/
|
||||
.svelte-kit
|
||||
build/
|
||||
|
||||
+2
-36
@@ -1,44 +1,10 @@
|
||||
# Our Node base image
|
||||
FROM node:20.8-alpine3.18 as base
|
||||
FROM node:20.8-alpine3.18
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
EXPOSE 3000
|
||||
RUN apk add --no-cache setpriv tini
|
||||
|
||||
FROM base as builder
|
||||
|
||||
RUN chown node:node /usr/src/app
|
||||
|
||||
COPY --chown=node:node package*.json ./
|
||||
|
||||
RUN npm ci
|
||||
|
||||
COPY --chown=node:node . .
|
||||
|
||||
EXPOSE 3000
|
||||
|
||||
FROM builder AS dev
|
||||
ENV CHOKIDAR_USEPOLLING=true
|
||||
EXPOSE 24678
|
||||
EXPOSE 3000
|
||||
CMD ["npm", "run", "dev"]
|
||||
|
||||
FROM builder AS prod
|
||||
|
||||
RUN npm run build
|
||||
RUN npm prune --omit=dev
|
||||
|
||||
FROM base
|
||||
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY --from=prod /usr/src/app/node_modules ./node_modules
|
||||
COPY --from=prod /usr/src/app/build ./build
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
COPY entrypoint.sh ./
|
||||
|
||||
ENTRYPOINT ["tini", "--", "/bin/sh"]
|
||||
|
||||
CMD ["entrypoint.sh"]
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Hau Tran
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,11 +0,0 @@
|
||||
#! /bin/sh
|
||||
|
||||
# Rebind env vars to PUBLIC_ for svelte
|
||||
export PUBLIC_IMMICH_SERVER_URL=$IMMICH_SERVER_URL
|
||||
export PUBLIC_IMMICH_API_URL_EXTERNAL=$IMMICH_API_URL_EXTERNAL
|
||||
|
||||
if [ "$(id -u)" -eq 0 ] && [ -n "$PUID" ] && [ -n "$PGID" ]; then
|
||||
exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups node /usr/src/app/build/index.js
|
||||
else
|
||||
exec node /usr/src/app/build/index.js
|
||||
fi
|
||||
Generated
+6
-204
@@ -31,7 +31,7 @@
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
"@faker-js/faker": "^8.0.0",
|
||||
"@floating-ui/dom": "^1.5.1",
|
||||
"@sveltejs/adapter-node": "^1.2.0",
|
||||
"@sveltejs/adapter-static": "^2.0.3",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@testing-library/jest-dom": "^6.0.0",
|
||||
"@testing-library/svelte": "^4.0.3",
|
||||
@@ -2989,98 +2989,6 @@
|
||||
"integrity": "sha512-C16M+IYz0rgRhWZdCmK+h58JMv8vijAA61gmz2rspCSwKwzBebpdcsiUmwrtJRdphuY30i6BSLEOP8ppbNLyLg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@rollup/plugin-commonjs": {
|
||||
"version": "25.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.4.tgz",
|
||||
"integrity": "sha512-L92Vz9WUZXDnlQQl3EwbypJR4+DM2EbsO+/KOcEkP4Mc6Ct453EeDB2uH9lgRwj4w5yflgNpq9pHOiY8aoUXBQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"commondir": "^1.0.1",
|
||||
"estree-walker": "^2.0.2",
|
||||
"glob": "^8.0.3",
|
||||
"is-reference": "1.2.1",
|
||||
"magic-string": "^0.27.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.68.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-json": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz",
|
||||
"integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/plugin-node-resolve": {
|
||||
"version": "15.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz",
|
||||
"integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.1",
|
||||
"@types/resolve": "1.20.2",
|
||||
"deepmerge": "^4.2.2",
|
||||
"is-builtin-module": "^3.2.1",
|
||||
"is-module": "^1.0.0",
|
||||
"resolve": "^1.22.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^2.78.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/pluginutils": {
|
||||
"version": "5.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.4.tgz",
|
||||
"integrity": "sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"rollup": "^1.20.0||^2.0.0||^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"rollup": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@sinclair/typebox": {
|
||||
"version": "0.27.8",
|
||||
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
|
||||
@@ -3110,19 +3018,13 @@
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg=="
|
||||
},
|
||||
"node_modules/@sveltejs/adapter-node": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-node/-/adapter-node-1.3.1.tgz",
|
||||
"integrity": "sha512-A0VgRQDCDPzdLNoiAbcOxGw4zT1Mc+n1LwT1OmO350R7WxrEqdMUChPPOd1iMfIDWlP4ie6E2d/WQf5es2d4Zw==",
|
||||
"node_modules/@sveltejs/adapter-static": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-2.0.3.tgz",
|
||||
"integrity": "sha512-VUqTfXsxYGugCpMqQv1U0LIdbR3S5nBkMMDmpjGVJyM6Q2jHVMFtdWJCkeHMySc6mZxJ+0eZK3T7IgmUCDrcUQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/plugin-commonjs": "^25.0.0",
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"rollup": "^3.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sveltejs/kit": "^1.0.0"
|
||||
"@sveltejs/kit": "^1.5.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@sveltejs/kit": {
|
||||
@@ -3678,12 +3580,6 @@
|
||||
"integrity": "sha512-I469DU0UXNC1aHepwirWhu9YKg5fkxohZD95Ey/5A7lovC+Siu+MCLffva87lnfThaOrw9Vb1DUN5t55oULAAw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/resolve": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.3.tgz",
|
||||
@@ -4639,18 +4535,6 @@
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/builtin-modules": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
|
||||
"integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/bytewise": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytewise/-/bytewise-1.1.0.tgz",
|
||||
@@ -4910,12 +4794,6 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -6013,12 +5891,6 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
@@ -6386,25 +6258,6 @@
|
||||
"resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
|
||||
"integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
|
||||
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^5.0.1",
|
||||
"once": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/glob-parent": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||
@@ -6417,27 +6270,6 @@
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/glob/node_modules/minimatch": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/global-prefix": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
|
||||
@@ -6921,21 +6753,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-builtin-module": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
|
||||
"integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"builtin-modules": "^3.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-callable": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
|
||||
@@ -7031,12 +6848,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
|
||||
"integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
@@ -7087,15 +6898,6 @@
|
||||
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
|
||||
"integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/is-regex": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
"@faker-js/faker": "^8.0.0",
|
||||
"@floating-ui/dom": "^1.5.1",
|
||||
"@sveltejs/adapter-node": "^1.2.0",
|
||||
"@sveltejs/adapter-static": "^2.0.3",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@testing-library/jest-dom": "^6.0.0",
|
||||
"@testing-library/svelte": "^4.0.3",
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import { BASE_PATH } from './open-api/base';
|
||||
import { DUMMY_BASE_URL, toPathString } from './open-api/common';
|
||||
import type { ApiParams } from './types';
|
||||
|
||||
export class ImmichApi {
|
||||
class ImmichApi {
|
||||
public activityApi: ActivityApi;
|
||||
public albumApi: AlbumApi;
|
||||
public libraryApi: LibraryApi;
|
||||
|
||||
Vendored
-5
@@ -3,11 +3,6 @@
|
||||
// See https://kit.svelte.dev/docs/types#app
|
||||
// for information about these interfaces
|
||||
declare namespace App {
|
||||
interface Locals {
|
||||
user?: import('@api').UserResponseDto;
|
||||
api: import('@api').ImmichApi;
|
||||
}
|
||||
|
||||
interface PageData {
|
||||
meta: {
|
||||
title: string;
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
document.documentElement.classList.remove('dark');
|
||||
}
|
||||
</script>
|
||||
<link rel="stylesheet" href="/custom.css" />
|
||||
</head>
|
||||
|
||||
<body class="bg-immich-bg dark:bg-immich-dark-bg">
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { HandleClientError } from '@sveltejs/kit';
|
||||
import type { AxiosError, AxiosResponse } from 'axios';
|
||||
|
||||
const LOG_PREFIX = '[hooks.client.ts]';
|
||||
const DEFAULT_MESSAGE = 'Hmm, not sure about that. Check the logs or open a ticket?';
|
||||
|
||||
const parseError = (error: unknown) => {
|
||||
const httpError = error as AxiosError;
|
||||
const request = httpError?.request as Request & { path: string };
|
||||
const response = httpError?.response as AxiosResponse<{
|
||||
message: string;
|
||||
statusCode: number;
|
||||
error: string;
|
||||
}>;
|
||||
|
||||
let code = response?.data?.statusCode || response?.status || httpError.code || '500';
|
||||
if (response) {
|
||||
code += ` - ${response.data?.error || response.statusText}`;
|
||||
}
|
||||
|
||||
if (request && response) {
|
||||
console.log({
|
||||
status: response.status,
|
||||
url: `${request.method} ${request.path}`,
|
||||
response: response.data || 'No data',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
message: response?.data?.message || httpError?.message || DEFAULT_MESSAGE,
|
||||
code,
|
||||
stack: httpError?.stack,
|
||||
};
|
||||
};
|
||||
|
||||
export const handleError: HandleClientError = ({ error }) => {
|
||||
const result = parseError(error);
|
||||
console.error(`${LOG_PREFIX}:handleError ${result.message}`);
|
||||
return result;
|
||||
};
|
||||
@@ -1,77 +0,0 @@
|
||||
import { env } from '$env/dynamic/public';
|
||||
import type { Handle, HandleServerError } from '@sveltejs/kit';
|
||||
import type { AxiosError, AxiosResponse } from 'axios';
|
||||
import { ImmichApi } from './api/api';
|
||||
|
||||
const LOG_PREFIX = '[hooks.server.ts]';
|
||||
|
||||
export const handle = (async ({ event, resolve }) => {
|
||||
const basePath = env.PUBLIC_IMMICH_SERVER_URL || 'http://immich-server:3001';
|
||||
const accessToken = event.cookies.get('immich_access_token');
|
||||
const api = new ImmichApi({ basePath, accessToken });
|
||||
|
||||
// API instance that should be used for all server-side requests.
|
||||
event.locals.api = api;
|
||||
|
||||
if (accessToken) {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
event.locals.user = user;
|
||||
} catch (err) {
|
||||
console.log(`${LOG_PREFIX} Unable to get my user`, parseError(err));
|
||||
|
||||
const apiError = err as AxiosError;
|
||||
// Ignore 401 unauthorized errors and log all others.
|
||||
if (apiError.response?.status && apiError.response?.status !== 401) {
|
||||
console.error(`${LOG_PREFIX}:handle`, err);
|
||||
} else if (!apiError.response?.status) {
|
||||
console.error(`${LOG_PREFIX}:handle`, apiError?.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const res = await resolve(event);
|
||||
|
||||
// The link header can grow quite big and has caused issues with our nginx
|
||||
// proxy returning a 502 Bad Gateway error. Therefore the header gets deleted.
|
||||
res.headers.delete('Link');
|
||||
|
||||
return res;
|
||||
}) satisfies Handle;
|
||||
|
||||
const DEFAULT_MESSAGE = 'Hmm, not sure about that. Check the logs or open a ticket?';
|
||||
|
||||
const parseError = (error: unknown) => {
|
||||
const httpError = error as AxiosError;
|
||||
const request = httpError?.request as Request & { path: string };
|
||||
const response = httpError?.response as AxiosResponse<{
|
||||
message: string;
|
||||
statusCode: number;
|
||||
error: string;
|
||||
}>;
|
||||
|
||||
let code = response?.data?.statusCode || response?.status || httpError.code || '500';
|
||||
if (response) {
|
||||
code += ` - ${response.data?.error || response.statusText}`;
|
||||
}
|
||||
|
||||
if (request && response) {
|
||||
console.log({
|
||||
status: response.status,
|
||||
url: `${request.method} ${request.path}`,
|
||||
response: response.data || 'No data',
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
message: response?.data?.message || httpError?.message || DEFAULT_MESSAGE,
|
||||
code,
|
||||
stack: httpError?.stack,
|
||||
};
|
||||
};
|
||||
|
||||
export const handleError: HandleServerError = ({ error }) => {
|
||||
const result = parseError(error);
|
||||
console.error(`${LOG_PREFIX}:handleError ${result.message}`);
|
||||
return result;
|
||||
};
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
const logOut = async () => {
|
||||
const { data } = await api.authenticationApi.logout();
|
||||
|
||||
await fetch('/auth/logout', { method: 'POST' });
|
||||
|
||||
goto(data.redirectUri || '/auth/login?autoLaunch=0');
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { AppRoute } from '../constants';
|
||||
|
||||
export interface AuthOptions {
|
||||
admin?: true;
|
||||
}
|
||||
|
||||
export const getAuthUser = async () => {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
return user;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: re-use already loaded user (once) instead of fetching on each page navigation
|
||||
export const authenticate = async (options?: AuthOptions) => {
|
||||
options = options || {};
|
||||
|
||||
const user = await getAuthUser();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
if (options.admin && !user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
export const isLoggedIn = async () => getAuthUser().then((user) => !!user);
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api, user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: albums } = await api.albumApi.getAllAlbums();
|
||||
|
||||
return {
|
||||
user: user,
|
||||
albums: albums,
|
||||
meta: {
|
||||
title: 'Albums',
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
const { data: albums } = await api.albumApi.getAllAlbums();
|
||||
|
||||
return {
|
||||
user,
|
||||
albums,
|
||||
meta: {
|
||||
title: 'Albums',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params, locals: { api, user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: album } = await api.albumApi.getAlbumInfo({ id: params.albumId, withoutAssets: true });
|
||||
|
||||
return {
|
||||
album,
|
||||
user,
|
||||
meta: {
|
||||
title: album.albumName,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
throw redirect(302, AppRoute.ALBUMS);
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
const user = await authenticate();
|
||||
const { data: album } = await api.albumApi.getAlbumInfo({ id: params.albumId, withoutAssets: true });
|
||||
|
||||
return {
|
||||
album,
|
||||
user,
|
||||
meta: {
|
||||
title: album.albumName,
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,15 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
export const prerender = false;
|
||||
|
||||
export const load: PageLoad = async ({ params, parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const albumId = params['albumId'];
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
const albumId = params.albumId;
|
||||
|
||||
if (albumId) {
|
||||
throw redirect(302, `${AppRoute.ALBUMS}/${albumId}`);
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Archive',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,13 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Archive',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,13 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
export const prerender = false;
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
export const load: PageLoad = async () => {
|
||||
throw redirect(302, AppRoute.ARCHIVE);
|
||||
};
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals, parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const { data: items } = await locals.api.searchApi.getExploreData();
|
||||
const { data: response } = await locals.api.personApi.getAllPeople({ withHidden: false });
|
||||
return {
|
||||
user,
|
||||
items,
|
||||
response,
|
||||
meta: {
|
||||
title: 'Explore',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,17 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
const { data: items } = await api.searchApi.getExploreData();
|
||||
const { data: response } = await api.personApi.getAllPeople({ withHidden: false });
|
||||
return {
|
||||
user,
|
||||
items,
|
||||
response,
|
||||
meta: {
|
||||
title: 'Explore',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Favorites',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Favorites',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else {
|
||||
throw redirect(302, AppRoute.FAVORITES);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async () => {
|
||||
throw redirect(302, AppRoute.FAVORITES);
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Map',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Map',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Memory',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Memory',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else {
|
||||
throw redirect(302, AppRoute.MEMORY);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
await authenticate();
|
||||
throw redirect(302, AppRoute.MEMORY);
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else {
|
||||
throw redirect(302, AppRoute.MEMORY);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,21 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ params, parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const { data: partner } = await api.userApi.getUserById({ id: params['userId'] });
|
||||
|
||||
return {
|
||||
user,
|
||||
partner,
|
||||
meta: {
|
||||
title: 'Partner',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
const user = await authenticate();
|
||||
|
||||
const { data: partner } = await api.userApi.getUserById({ id: params.userId });
|
||||
|
||||
return {
|
||||
user,
|
||||
partner,
|
||||
meta: {
|
||||
title: 'Partner',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals, parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const { data: people } = await locals.api.personApi.getAllPeople({ withHidden: true });
|
||||
return {
|
||||
user,
|
||||
people,
|
||||
meta: {
|
||||
title: 'People',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
|
||||
const { data: people } = await api.personApi.getAllPeople({ withHidden: true });
|
||||
return {
|
||||
user,
|
||||
people,
|
||||
meta: {
|
||||
title: 'People',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,22 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals, parent, params }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const { data: person } = await locals.api.personApi.getPerson({ id: params.personId });
|
||||
const { data: statistics } = await locals.api.personApi.getPersonStatistics({ id: params.personId });
|
||||
|
||||
return {
|
||||
user,
|
||||
person,
|
||||
statistics,
|
||||
meta: {
|
||||
title: person.name || 'Person',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
const user = await authenticate();
|
||||
|
||||
const { data: person } = await api.personApi.getPerson({ id: params.personId });
|
||||
const { data: statistics } = await api.personApi.getPersonStatistics({ id: params.personId });
|
||||
|
||||
return {
|
||||
user,
|
||||
person,
|
||||
statistics,
|
||||
meta: {
|
||||
title: person.name || 'Person',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,14 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
export const prerender = false;
|
||||
|
||||
export const load: PageLoad = async ({ params, parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const personId = params['personId'];
|
||||
throw redirect(302, `${AppRoute.PEOPLE}/${personId}`);
|
||||
};
|
||||
export const load = (async ({ params }) => {
|
||||
throw redirect(302, `${AppRoute.PEOPLE}/${params.personId}`);
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Photos',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Photos',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,15 +0,0 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals, parent, url }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const term = url.searchParams.get('q') || url.searchParams.get('query') || undefined;
|
||||
|
||||
const { data: results } = await locals.api.searchApi.search({}, { params: url.searchParams });
|
||||
|
||||
return {
|
||||
user,
|
||||
term,
|
||||
results,
|
||||
meta: {
|
||||
title: 'Search',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
const url = new URL(location.href);
|
||||
const term = url.searchParams.get('q') || url.searchParams.get('query') || undefined;
|
||||
|
||||
const { data: results } = await api.searchApi.search({}, { params: url.searchParams });
|
||||
|
||||
return {
|
||||
user,
|
||||
term,
|
||||
results,
|
||||
meta: {
|
||||
title: 'Search',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,13 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
export const prerender = false;
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
export const load = (async () => {
|
||||
throw redirect(302, AppRoute.SEARCH);
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
+10
-9
@@ -1,31 +1,32 @@
|
||||
import featurePanelUrl from '$lib/assets/feature-panel.png';
|
||||
import { api as clientApi, ThumbnailFormat } from '@api';
|
||||
import { getAuthUser } from '$lib/utils/auth';
|
||||
import { api, ThumbnailFormat } from '@api';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params, locals: { api }, cookies }) => {
|
||||
export const load = (async ({ params }) => {
|
||||
const { key } = params;
|
||||
const token = cookies.get('immich_shared_link_token');
|
||||
const user = await getAuthUser();
|
||||
|
||||
try {
|
||||
const { data: sharedLink } = await api.sharedLinkApi.getMySharedLink({ key, token });
|
||||
const { data: sharedLink } = await api.sharedLinkApi.getMySharedLink({ key });
|
||||
|
||||
const assetCount = sharedLink.assets.length;
|
||||
const assetId = sharedLink.album?.albumThumbnailAssetId || sharedLink.assets[0]?.id;
|
||||
|
||||
return {
|
||||
user,
|
||||
sharedLink,
|
||||
meta: {
|
||||
title: sharedLink.album ? sharedLink.album.albumName : 'Public Share',
|
||||
description: sharedLink.description || `${assetCount} shared photos & videos.`,
|
||||
imageUrl: assetId
|
||||
? clientApi.getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key)
|
||||
: featurePanelUrl,
|
||||
imageUrl: assetId ? api.getAssetThumbnailUrl(assetId, ThumbnailFormat.Webp, sharedLink.key) : featurePanelUrl,
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
// handle unauthorized error
|
||||
// TODO this doesn't allow for 404 shared links anymore
|
||||
if ((e as AxiosError).response?.status === 401) {
|
||||
return {
|
||||
passwordRequired: true,
|
||||
@@ -40,4 +41,4 @@ export const load = (async ({ params, locals: { api }, cookies }) => {
|
||||
message: 'Invalid shared link',
|
||||
});
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,19 +0,0 @@
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params, locals: { api } }) => {
|
||||
const { key, assetId } = params;
|
||||
const { data: asset } = await api.assetApi.getAssetById({ id: assetId, key });
|
||||
|
||||
if (!asset) {
|
||||
throw error(404, 'Asset not found');
|
||||
}
|
||||
|
||||
return {
|
||||
asset,
|
||||
key,
|
||||
meta: {
|
||||
title: 'Public Share',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,15 @@
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ params }) => {
|
||||
const { key, assetId } = params;
|
||||
const { data: asset } = await api.assetApi.getAssetById({ id: assetId, key });
|
||||
|
||||
return {
|
||||
asset,
|
||||
key,
|
||||
meta: {
|
||||
title: 'Public Share',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api, user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: sharedAlbums } = await api.albumApi.getAllAlbums({ shared: true });
|
||||
const { data: partners } = await api.partnerApi.getPartners({ direction: 'shared-with' });
|
||||
|
||||
return {
|
||||
user,
|
||||
sharedAlbums,
|
||||
partners,
|
||||
meta: {
|
||||
title: 'Sharing',
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
const { data: sharedAlbums } = await api.albumApi.getAllAlbums({ shared: true });
|
||||
const { data: partners } = await api.partnerApi.getPartners({ direction: 'shared-with' });
|
||||
|
||||
return {
|
||||
user,
|
||||
sharedAlbums,
|
||||
partners,
|
||||
meta: {
|
||||
title: 'Sharing',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Shared Links',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Shared Links',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Trash',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,12 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Trash',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,13 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
export const prerender = false;
|
||||
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
export const load = (async () => {
|
||||
throw redirect(302, AppRoute.TRASH);
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals }) => {
|
||||
const { user } = await parent();
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
}
|
||||
|
||||
const { data: keys } = await locals.api.keyApi.getApiKeys();
|
||||
const { data: devices } = await locals.api.authenticationApi.getAuthDevices();
|
||||
|
||||
return {
|
||||
user,
|
||||
keys,
|
||||
devices,
|
||||
meta: {
|
||||
title: 'Settings',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
|
||||
const { data: keys } = await api.keyApi.getApiKeys();
|
||||
const { data: devices } = await api.authenticationApi.getAuthDevices();
|
||||
|
||||
return {
|
||||
user,
|
||||
keys,
|
||||
devices,
|
||||
meta: {
|
||||
title: 'Settings',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { LayoutServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
return { user };
|
||||
}) satisfies LayoutServerLoad;
|
||||
@@ -24,7 +24,10 @@
|
||||
export let data: LayoutData;
|
||||
let albumId: string | undefined;
|
||||
|
||||
if ($page.route.id?.startsWith('/(user)/share/[key]')) {
|
||||
const isSharedLinkRoute = (route: string | null) => route?.startsWith('/(user)/share/[key]');
|
||||
const isAuthRoute = (route?: string) => route?.startsWith('/auth');
|
||||
|
||||
if (isSharedLinkRoute($page.route?.id)) {
|
||||
api.setKey($page.params.key);
|
||||
}
|
||||
|
||||
@@ -32,11 +35,11 @@
|
||||
const fromRoute = from?.route?.id || '';
|
||||
const toRoute = to?.route?.id || '';
|
||||
|
||||
if (fromRoute.startsWith('/auth') && !toRoute.startsWith('/auth')) {
|
||||
if (isAuthRoute(fromRoute) && !isAuthRoute(toRoute)) {
|
||||
openWebsocketConnection();
|
||||
}
|
||||
|
||||
if (!fromRoute.startsWith('/auth') && toRoute.startsWith('/auth')) {
|
||||
if (!isAuthRoute(fromRoute) && isAuthRoute(toRoute)) {
|
||||
closeWebsocketConnection();
|
||||
}
|
||||
|
||||
@@ -80,7 +83,6 @@
|
||||
<svelte:head>
|
||||
<title>{$page.data.meta?.title || 'Web'} - Immich</title>
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<link rel="stylesheet" href="/custom.css" />
|
||||
<meta name="theme-color" content="currentColor" />
|
||||
<FaviconHeader />
|
||||
<AppleHeader />
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { api } from '../api';
|
||||
import type { LayoutLoad } from './$types';
|
||||
|
||||
const getUser = async () => {
|
||||
try {
|
||||
const { data: user } = await api.userApi.getMyUserInfo();
|
||||
return user;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const ssr = false;
|
||||
export const csr = true;
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await getUser();
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Immich',
|
||||
},
|
||||
};
|
||||
}) satisfies LayoutLoad;
|
||||
@@ -1,17 +1,19 @@
|
||||
export const prerender = false;
|
||||
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import { api } from '../api';
|
||||
import { isLoggedIn } from '../lib/utils/auth';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
if (user) {
|
||||
export const ssr = false;
|
||||
export const csr = true;
|
||||
|
||||
export const load = (async () => {
|
||||
const authenticated = await isLoggedIn();
|
||||
if (authenticated) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
|
||||
if (data.isInitialized) {
|
||||
// Redirect to login page if there exists an admin account (i.e. server is initialized)
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
@@ -23,4 +25,4 @@ export const load = (async ({ parent, locals: { api } }) => {
|
||||
description: 'Immich Web Interface',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
const endpoint = process.env.IMMICH_API_URL_EXTERNAL || '/api';
|
||||
|
||||
export const GET = async () => {
|
||||
return json({
|
||||
api: {
|
||||
endpoint,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
throw redirect(302, AppRoute.ADMIN_USER_MANAGEMENT);
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
throw redirect(302, AppRoute.ADMIN_USER_MANAGEMENT);
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user, api } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
try {
|
||||
const { data: jobs } = await api.jobApi.getAllJobsStatus();
|
||||
|
||||
return {
|
||||
user,
|
||||
jobs,
|
||||
meta: {
|
||||
title: 'Job Status',
|
||||
},
|
||||
};
|
||||
} catch (err) {
|
||||
console.error('[jobs] > getAllJobsStatus', err);
|
||||
throw err;
|
||||
}
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,17 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate({ admin: true });
|
||||
|
||||
const { data: jobs } = await api.jobApi.getAllJobsStatus();
|
||||
|
||||
return {
|
||||
user,
|
||||
jobs,
|
||||
meta: {
|
||||
title: 'Job Status',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,26 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const {
|
||||
data: { orphans, extras },
|
||||
} = await api.auditApi.getAuditFiles();
|
||||
|
||||
return {
|
||||
user,
|
||||
orphans,
|
||||
extras,
|
||||
meta: {
|
||||
title: 'Repair',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,19 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate({ admin: true });
|
||||
const {
|
||||
data: { orphans, extras },
|
||||
} = await api.auditApi.getAuditFiles();
|
||||
|
||||
return {
|
||||
user,
|
||||
orphans,
|
||||
extras,
|
||||
meta: {
|
||||
title: 'Repair',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: stats } = await api.serverInfoApi.getServerStatistics();
|
||||
|
||||
return {
|
||||
user,
|
||||
stats,
|
||||
meta: {
|
||||
title: 'Server Stats',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate({ admin: true });
|
||||
const { data: stats } = await api.serverInfoApi.getServerStatistics();
|
||||
|
||||
return {
|
||||
user,
|
||||
stats,
|
||||
meta: {
|
||||
title: 'Server Stats',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: configs } = await api.systemConfigApi.getConfig();
|
||||
|
||||
return {
|
||||
user,
|
||||
configs,
|
||||
meta: {
|
||||
title: 'System Settings',
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate({ admin: true });
|
||||
const { data: configs } = await api.systemConfigApi.getConfig();
|
||||
|
||||
return {
|
||||
user,
|
||||
configs,
|
||||
meta: {
|
||||
title: 'System Settings',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,23 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ parent, locals: { api } }) => {
|
||||
const { user } = await parent();
|
||||
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.isAdmin) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
const { data: allUsers } = await api.userApi.getAllUsers({ isAll: false });
|
||||
|
||||
return {
|
||||
user,
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'User Management',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,16 @@
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { api } from '@api';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate({ admin: true });
|
||||
const { data: allUsers } = await api.userApi.getAllUsers({ isAll: false });
|
||||
|
||||
return {
|
||||
user,
|
||||
allUsers,
|
||||
meta: {
|
||||
title: 'User Management',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,18 +0,0 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { user } }) => {
|
||||
if (!user) {
|
||||
throw redirect(302, AppRoute.AUTH_LOGIN);
|
||||
} else if (!user.shouldChangePassword) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Change Password',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
@@ -0,0 +1,18 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { authenticate } from '$lib/utils/auth';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async () => {
|
||||
const user = await authenticate();
|
||||
if (!user.shouldChangePassword) {
|
||||
throw redirect(302, AppRoute.PHOTOS);
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
meta: {
|
||||
title: 'Change Password',
|
||||
},
|
||||
};
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api } }) => {
|
||||
export const load = (async () => {
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
if (!data.isInitialized) {
|
||||
// Admin not registered
|
||||
@@ -14,4 +15,4 @@ export const load = (async ({ locals: { api } }) => {
|
||||
title: 'Login',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,12 +0,0 @@
|
||||
import { api } from '@api';
|
||||
import type { RequestHandler } from '@sveltejs/kit';
|
||||
import { json } from '@sveltejs/kit';
|
||||
|
||||
export const POST = (async ({ cookies }) => {
|
||||
api.removeAccessToken();
|
||||
|
||||
cookies.delete('immich_auth_type', { path: '/' });
|
||||
cookies.delete('immich_access_token', { path: '/' });
|
||||
|
||||
return json({ ok: true });
|
||||
}) satisfies RequestHandler;
|
||||
+4
-3
@@ -1,8 +1,9 @@
|
||||
import { AppRoute } from '$lib/constants';
|
||||
import { api } from '@api';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageServerLoad } from './$types';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load = (async ({ locals: { api } }) => {
|
||||
export const load = (async () => {
|
||||
const { data } = await api.serverInfoApi.getServerConfig();
|
||||
if (data.isInitialized) {
|
||||
// Admin has been registered, redirect to login
|
||||
@@ -14,4 +15,4 @@ export const load = (async ({ locals: { api } }) => {
|
||||
title: 'Admin Registration',
|
||||
},
|
||||
};
|
||||
}) satisfies PageServerLoad;
|
||||
}) satisfies PageLoad;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { RequestHandler, text } from '@sveltejs/kit';
|
||||
export const GET = (async ({ locals: { api } }) => {
|
||||
const {
|
||||
data: { customCss },
|
||||
} = await api.serverInfoApi.getTheme();
|
||||
return text(customCss, {
|
||||
headers: {
|
||||
'Content-Type': 'text/css',
|
||||
},
|
||||
});
|
||||
}) satisfies RequestHandler;
|
||||
+10
-2
@@ -1,4 +1,4 @@
|
||||
import adapter from '@sveltejs/adapter-node';
|
||||
import adapter from '@sveltejs/adapter-static';
|
||||
import preprocess from 'svelte-preprocess';
|
||||
|
||||
/** @type {import('@sveltejs/kit').Config} */
|
||||
@@ -11,7 +11,15 @@ const config = {
|
||||
handler(warning);
|
||||
},
|
||||
kit: {
|
||||
adapter: adapter({ out: 'build' }),
|
||||
adapter: adapter({
|
||||
// default options are shown. On some platforms
|
||||
// these options are set automatically — see below
|
||||
pages: 'build',
|
||||
assets: 'build',
|
||||
fallback: 'index.html',
|
||||
precompress: false,
|
||||
strict: true,
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+11
-8
@@ -1,6 +1,14 @@
|
||||
import { sveltekit } from '@sveltejs/kit/vite';
|
||||
import path from 'path';
|
||||
|
||||
const upstream = {
|
||||
target: process.env.IMMICH_SERVER_URL || 'http://immich-server:3001/',
|
||||
secure: true,
|
||||
changeOrigin: true,
|
||||
logLevel: 'debug',
|
||||
ws: true,
|
||||
};
|
||||
|
||||
/** @type {import('vite').UserConfig} */
|
||||
const config = {
|
||||
resolve: {
|
||||
@@ -12,14 +20,9 @@ const config = {
|
||||
server: {
|
||||
// connect to a remote backend during web-only development
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: process.env.PUBLIC_IMMICH_SERVER_URL,
|
||||
secure: true,
|
||||
changeOrigin: true,
|
||||
logLevel: 'debug',
|
||||
rewrite: (path) => path.replace(/^\/api/, ''),
|
||||
ws: true,
|
||||
},
|
||||
'/api': upstream,
|
||||
'/.well-known/immich': upstream,
|
||||
'/custom.css': upstream,
|
||||
},
|
||||
},
|
||||
plugins: [sveltekit()],
|
||||
|
||||
Reference in New Issue
Block a user