Use cookies for client requests (#377)

* Use cookie for frontend request

* Remove api helper to use SDK

* Added error handling to status box

* Remove additional places that check for session.user

* Refactor sending password

* prettier clean up

* remove deadcode

* Move all authentication requests to the client

* refactor upload panel to only fetch assets after the upload panel disappear

* Added keydown to remove focus on title change on album viewer
This commit is contained in:
Alex
2022-07-26 12:28:07 -05:00
committed by GitHub
parent 2ebb755f00
commit 83cbf51704
54 changed files with 4954 additions and 4540 deletions

View File

@@ -2,11 +2,7 @@
import type { Load } from '@sveltejs/kit';
import { checkAppVersion } from '$lib/utils/check-app-version';
export const load: Load = async ({ url, session }) => {
if (session.user) {
api.setAccessToken(session.user.accessToken);
}
export const load: Load = async ({ url }) => {
return {
props: { url }
};
@@ -17,12 +13,10 @@
import '../app.css';
import { fade } from 'svelte/transition';
import DownloadPanel from '$lib/components/asset-viewer/download-panel.svelte';
import AnnouncementBox from '$lib/components/shared-components/announcement-box.svelte';
import UploadPanel from '$lib/components/shared-components/upload-panel.svelte';
import { onMount } from 'svelte';
import { api } from '@api';
export let url: string;
let shouldShowAnnouncement: boolean;
@@ -43,7 +37,9 @@
<div in:fade={{ duration: 100 }}>
<slot />
<DownloadPanel />
<UploadPanel />
{#if shouldShowAnnouncement}
<AnnouncementBox
{localVersion}

View File

@@ -1,34 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { api } from '@api';
export const POST: RequestHandler = async ({ request }) => {
const form = await request.formData();
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const { status } = await api.userApi.createUser({
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName)
});
if (status === 201) {
return {
status: 201,
body: {
success: 'Succesfully create user account'
}
};
} else {
return {
status: 400,
body: {
error: 'Error create user account'
}
};
}
};

View File

@@ -2,23 +2,24 @@
import type { Load } from '@sveltejs/kit';
import { api, UserResponseDto } from '@api';
export const load: Load = async ({ session }) => {
if (!session.user) {
export const load: Load = async () => {
try {
const { data: allUsers } = await api.userApi.getAllUsers(false);
const { data: user } = await api.userApi.getMyUserInfo();
return {
status: 200,
props: {
user: user,
allUsers: allUsers
}
};
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
const { data } = await api.userApi.getAllUsers(false);
return {
status: 200,
props: {
user: session.user,
allUsers: data
}
};
};
</script>
@@ -35,7 +36,7 @@
import CreateUserForm from '$lib/components/forms/create-user-form.svelte';
import StatusBox from '$lib/components/shared-components/status-box.svelte';
let selectedAction: AdminSideBarSelection;
let selectedAction: AdminSideBarSelection = AdminSideBarSelection.USER_MANAGEMENT;
export let user: ImmichUser;
export let allUsers: UserResponseDto[];

View File

@@ -4,38 +4,39 @@
import type { Load } from '@sveltejs/kit';
import { AlbumResponseDto, api } from '@api';
export const load: Load = async ({ session, params }) => {
if (!session.user) {
export const load: Load = async ({ params }) => {
try {
const albumId = params['albumId'];
const { data: albumInfo } = await api.albumApi.getAlbumInfo(albumId);
return {
status: 200,
props: {
album: albumInfo
}
};
} catch (e) {
if (e instanceof AxiosError) {
if (e.response?.status === 404) {
return {
status: 302,
redirect: '/albums'
};
}
}
return {
status: 302,
redirect: '/auth/login'
};
}
const albumId = params['albumId'];
let album: AlbumResponseDto;
try {
const { data } = await api.albumApi.getAlbumInfo(albumId);
album = data;
} catch (e) {
return {
status: 302,
redirect: '/albums'
};
}
return {
status: 200,
props: {
album: album
}
};
};
</script>
<script lang="ts">
import AlbumViewer from '$lib/components/album-page/album-viewer.svelte';
import { AxiosError } from 'axios';
export let album: AlbumResponseDto;
</script>

View File

@@ -1,15 +1,19 @@
<script context="module" lang="ts">
export const prerender = false;
import { api } from '@api';
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ session, params }) => {
if (!session.user) {
export const load: Load = async ({ params }) => {
try {
await api.userApi.getMyUserInfo();
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
const albumId = params['albumId'];
if (albumId) {

View File

@@ -9,29 +9,24 @@
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
import { AlbumResponseDto, api } from '@api';
export const load: Load = async ({ session }) => {
if (!session.user) {
export const load: Load = async () => {
try {
const { data: user } = await api.userApi.getMyUserInfo();
const { data: albums } = await api.albumApi.getAllAlbums();
return {
status: 200,
props: {
user: user,
albums: albums
}
};
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
let albums: AlbumResponseDto[] = [];
try {
const { data } = await api.albumApi.getAllAlbums();
albums = data;
} catch (e) {
console.log('Error [getAllAlbums] ', e);
}
return {
status: 200,
props: {
user: session.user,
albums: albums
}
};
};
</script>

View File

@@ -3,14 +3,7 @@
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ session }) => {
if (!session.user) {
return {
status: 302,
redirect: '/auth/login',
};
}
export const load: Load = async () => {
try {
const { data: userInfo } = await api.userApi.getMyUserInfo();
@@ -18,20 +11,19 @@
return {
status: 200,
props: {
user: userInfo,
},
user: userInfo
}
};
} else {
return {
status: 302,
redirect: '/photos',
redirect: '/photos'
};
}
} catch (e) {
console.log('ERROR Getting user info', e);
return {
status: 302,
redirect: '/photos',
redirect: '/auth/login'
};
}
};

View File

@@ -1,38 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { api } from '@api';
export const POST: RequestHandler = async ({ request, locals }) => {
if (!locals.user) {
return {
status: 401,
body: {
error: 'Unauthorized'
}
};
}
const form = await request.formData();
const password = form.get('password');
const { status } = await api.userApi.updateUser({
id: locals.user.id,
password: String(password),
shouldChangePassword: false
});
if (status === 200) {
return {
status: 200,
body: {
success: 'Succesfully change password'
}
};
} else {
return {
status: 400,
body: {
error: 'Error change password'
}
};
}
};

View File

@@ -1,59 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import * as cookie from 'cookie';
import { api } from '@api';
export const POST: RequestHandler = async ({ request }) => {
const form = await request.formData();
const email = form.get('email');
const password = form.get('password');
try {
const { data: authUser } = await api.authenticationApi.login({
email: String(email),
password: String(password)
});
return {
status: 200,
body: {
user: {
id: authUser.userId,
accessToken: authUser.accessToken,
firstName: authUser.firstName,
lastName: authUser.lastName,
isAdmin: authUser.isAdmin,
email: authUser.userEmail,
shouldChangePassword: authUser.shouldChangePassword
},
success: 'success'
},
headers: {
'Set-Cookie': cookie.serialize(
'session',
JSON.stringify({
id: authUser.userId,
accessToken: authUser.accessToken,
firstName: authUser.firstName,
lastName: authUser.lastName,
isAdmin: authUser.isAdmin,
email: authUser.userEmail
}),
{
path: '/',
httpOnly: true,
sameSite: 'strict',
maxAge: 60 * 60 * 24 * 30
}
)
}
};
} catch (error) {
return {
status: 400,
body: {
error: 'Incorrect email or password'
}
};
}
};

View File

@@ -1,9 +1,15 @@
import { api } from '@api';
import type { RequestHandler } from '@sveltejs/kit';
export const POST: RequestHandler = async () => {
api.removeAccessToken();
return {
headers: {
'Set-Cookie': 'session=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
'Set-Cookie': [
'immich_is_authenticated=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT;',
'immich_access_token=delete; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'
]
},
body: {
ok: true

View File

@@ -1,25 +1,19 @@
<script context="module" lang="ts">
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ session }) => {
export const load: Load = async () => {
const { data } = await api.userApi.getUserCount();
if (data.userCount != 0) {
// Admin has been registered, redirect to login
if (!session.user) {
return {
status: 302,
redirect: '/auth/login',
};
} else {
return {
status: 302,
redirect: '/photos',
};
}
return {
status: 302,
redirect: '/auth/login'
};
}
return {};
return {
status: 200
};
};
</script>

View File

@@ -1,34 +0,0 @@
import type { RequestHandler } from '@sveltejs/kit';
import { api } from '@api';
export const POST: RequestHandler = async ({ request }) => {
const form = await request.formData();
const email = form.get('email');
const password = form.get('password');
const firstName = form.get('firstName');
const lastName = form.get('lastName');
const { status } = await api.authenticationApi.adminSignUp({
email: String(email),
password: String(password),
firstName: String(firstName),
lastName: String(lastName)
});
if (status === 201) {
return {
status: 201,
body: {
success: 'Succesfully create admin account'
}
};
} else {
return {
status: 400,
body: {
error: 'Error create admin account'
}
};
}
};

View File

@@ -3,21 +3,23 @@
import type { Load } from '@sveltejs/kit';
import { api } from '@api';
export const load: Load = async ({ session }) => {
const { data } = await api.userApi.getUserCount();
export const load: Load = async () => {
try {
const { data: user } = await api.userApi.getMyUserInfo();
if (session.user) {
return {
status: 302,
redirect: '/photos',
redirect: '/photos'
};
}
} catch (e) {}
const { data } = await api.userApi.getUserCount();
return {
status: 200,
props: {
isAdminUserExist: data.userCount == 0 ? false : true,
},
isAdminUserExist: data.userCount == 0 ? false : true
}
};
};
</script>

View File

@@ -1,19 +1,21 @@
<script context="module" lang="ts">
export const prerender = false;
import { api } from '@api';
import type { Load } from '@sveltejs/kit';
export const load: Load = async ({ session }) => {
if (!session.user) {
export const load: Load = async () => {
try {
await api.userApi.getMyUserInfo();
return {
status: 302,
redirect: '/auth/login',
redirect: '/photos'
};
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
return {
status: 302,
redirect: '/photos',
};
};
</script>

View File

@@ -4,41 +4,39 @@
import type { Load } from '@sveltejs/kit';
import { getAssetsInfo } from '$lib/stores/assets';
export const load: Load = async ({ session }) => {
if (!session.user) {
export const load: Load = async () => {
try {
const { data } = await api.userApi.getMyUserInfo();
await getAssetsInfo();
return {
status: 200,
props: {
user: data
}
};
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
await getAssetsInfo();
return {
status: 200,
props: {
user: session.user
}
};
};
</script>
<script lang="ts">
import type { ImmichUser } from '$lib/models/immich-user';
import NavigationBar from '$lib/components/shared-components/navigation-bar.svelte';
import CheckCircle from 'svelte-material-icons/CheckCircle.svelte';
import { fly } from 'svelte/transition';
import { session } from '$app/stores';
import { assetsGroupByDate, flattenAssetGroupByDate } from '$lib/stores/assets';
import ImmichThumbnail from '$lib/components/shared-components/immich-thumbnail.svelte';
import moment from 'moment';
import AssetViewer from '$lib/components/asset-viewer/asset-viewer.svelte';
import { fileUploader } from '$lib/utils/file-uploader';
import { AssetResponseDto } from '@api';
import { api, AssetResponseDto, UserResponseDto } from '@api';
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
export let user: ImmichUser;
export let user: UserResponseDto;
let selectedGroupThumbnail: number | null;
let isMouseOverGroup: boolean;
@@ -67,30 +65,28 @@
};
const uploadClickedHandler = async () => {
if ($session.user) {
try {
let fileSelector = document.createElement('input');
try {
let fileSelector = document.createElement('input');
fileSelector.type = 'file';
fileSelector.multiple = true;
fileSelector.accept = 'image/*,video/*,.heic,.heif';
fileSelector.type = 'file';
fileSelector.multiple = true;
fileSelector.accept = 'image/*,video/*,.heic,.heif';
fileSelector.onchange = async (e: any) => {
const files = Array.from<File>(e.target.files);
fileSelector.onchange = async (e: any) => {
const files = Array.from<File>(e.target.files);
const acceptedFile = files.filter(
(e) => e.type.split('/')[0] === 'video' || e.type.split('/')[0] === 'image'
);
const acceptedFile = files.filter(
(e) => e.type.split('/')[0] === 'video' || e.type.split('/')[0] === 'image'
);
for (const asset of acceptedFile) {
await fileUploader(asset, $session.user!.accessToken);
}
};
for (const asset of acceptedFile) {
await fileUploader(asset);
}
};
fileSelector.click();
} catch (e) {
console.log('Error seelcting file', e);
}
fileSelector.click();
} catch (e) {
console.log('Error seelcting file', e);
}
};

View File

@@ -4,30 +4,36 @@
import type { Load } from '@sveltejs/kit';
import { AlbumResponseDto, api, UserResponseDto } from '@api';
export const load: Load = async ({ session }) => {
if (!session.user) {
export const load: Load = async () => {
try {
const { data: user } = await api.userApi.getMyUserInfo();
const { data: sharedAlbums } = await api.albumApi.getAllAlbums(true);
return {
status: 200,
props: {
user: user,
sharedAlbums: sharedAlbums
}
};
} catch (e) {
return {
status: 302,
redirect: '/auth/login'
};
}
let sharedAlbums: AlbumResponseDto[] = [];
try {
const { data } = await api.albumApi.getAllAlbums(true);
sharedAlbums = data;
} catch (e) {
console.log('Error [getAllAlbums] ', e);
}
return {
status: 200,
props: {
user: session.user,
sharedAlbums: sharedAlbums
}
};
};
</script>
<script lang="ts">
import NavigationBar from '$lib/components/shared-components/navigation-bar.svelte';
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
import PlusBoxOutline from 'svelte-material-icons/PlusBoxOutline.svelte';
import SharedAlbumListTile from '$lib/components/sharing-page/shared-album-list-tile.svelte';
import { goto } from '$app/navigation';
export let user: UserResponseDto;
export let sharedAlbums: AlbumResponseDto[];
const createSharedAlbum = async () => {
try {
@@ -40,28 +46,6 @@
console.log('Error [createAlbum] ', e);
}
};
const deleteAlbum = async (album: AlbumResponseDto) => {
try {
await api.albumApi.deleteAlbum(album.id);
return true;
} catch (e) {
console.log('Error [deleteAlbum] ', e);
return false;
}
};
</script>
<script lang="ts">
import NavigationBar from '$lib/components/shared-components/navigation-bar.svelte';
import SideBar from '$lib/components/shared-components/side-bar/side-bar.svelte';
import PlusBoxOutline from 'svelte-material-icons/PlusBoxOutline.svelte';
import AlbumCard from '$lib/components/album-page/album-card.svelte';
import SharedAlbumListTile from '$lib/components/sharing-page/shared-album-list-tile.svelte';
import { goto } from '$app/navigation';
export let user: UserResponseDto;
export let sharedAlbums: AlbumResponseDto[];
</script>
<svelte:head>