From 55e0e1f91e823ee667d94c6231ab35b675a06a74 Mon Sep 17 00:00:00 2001 From: split Date: Wed, 10 Jul 2024 22:01:20 -0700 Subject: [PATCH] add profile picture set --- bun.lockb | Bin 76572 -> 76932 bytes imagemagick.policy.xml | 134 +++++++++++++++++++++++++++++++++ package.json | 3 +- src/lib/avatars.ts | 73 ++++++++++++++++-- src/lib/oidc.ts | 19 ++++- src/routes/+layout.svelte | 2 +- src/routes/set/+page.server.ts | 32 +++++++- src/routes/set/+page.svelte | 19 ++++- static/default/1024.png | Bin 0 -> 32170 bytes 9 files changed, 267 insertions(+), 15 deletions(-) create mode 100644 imagemagick.policy.xml create mode 100644 static/default/1024.png diff --git a/bun.lockb b/bun.lockb index 9df74ce372009629acdb3530de89313b57d724e0..3e6971a13f484059dafa57951915acfdd9745caf 100755 GIT binary patch delta 11924 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 Wh!*5L*p_$EhBb#bUZxFCFaIYZz91a{ delta 11680 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index fa40232..ee2b869 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,8 @@ "@fontsource-variable/inter": "^5.0.18", "@fontsource-variable/noto-sans-mono": "^5.0.20", "@prisma/client": "5.16.2", - "magickwand.js": "^1.1.0" + "magickwand.js": "^1.1.0", + "mime": "^4.0.4" }, "trustedDependencies": [ "magickwand.js" diff --git a/src/lib/avatars.ts b/src/lib/avatars.ts index 6357bdb..1e62eb4 100644 --- a/src/lib/avatars.ts +++ b/src/lib/avatars.ts @@ -1,14 +1,19 @@ -import { readdir } from "node:fs/promises" +import { mkdir, readdir, rm } from "node:fs/promises" import { existsSync } from "node:fs" -import { basename, join } from "node:path" +import { join } from "node:path" import { prisma } from "./clientsingleton" +import configuration from "./configuration" +import { Magick, MagickCore } from "magickwand.js" +import mime from "mime" + +Magick.SetSecurityPolicy(await Bun.file('./imagemagick.policy.xml').text()) // todo: make customizable export const avatarDirectory = "./.data/avatars" export const defaultAvatarDirectory = "./static/default/" -export const renderSizes = [ 512, 256, 128, 64, 32 ] +export const renderSizes = [ 1024, 512, 256, 128, 64, 32 ] -export async function getPathToAvatarForUid(uid?: string, size: string = "index") { +export async function getPathToAvatarForUid(uid?: string, size: string = "512") { if (uid?.includes("/")) throw Error("UID cannot include /") @@ -22,12 +27,68 @@ export async function getPathToAvatarForUid(uid?: string, size: string = "index" return join(userAvatarDirectory, targetAvatar) } -export async function getPathToAvatarForIdentifier(identifier: string, size: string = "index") { +export async function getPathToAvatarForIdentifier(identifier: string, size: string = "512") { let user = await prisma.user.findFirst({ where: { identifier } }) - return getPathToAvatarForUid(user?.userId || "", size) + return getPathToAvatarForUid(user?.userId, size) +} + +export async function rerenderAvatar(bin: ArrayBuffer, squareSize?: number) { + let img = new Magick.Image; + // read file + await img.readAsync(new Magick.Blob(bin),"") + if (squareSize) { + // resize, but don't upscale, while filling without squishing + await img.scaleAsync(`${squareSize}x${squareSize}^>`) + } + // center crop + const size = img.size() + squareSize = Math.min(size.width(), size.height()) + await img.extentAsync(`${squareSize}x${squareSize}`, MagickCore.CenterGravity) + + // return avatar buffer + let tempBlob = new Magick.Blob() + await img.writeAsync(tempBlob) + return tempBlob.dataAsync() +} + +export async function setNewAvatar(uid: string, avatar?: File) { + if (uid?.includes("/")) + throw Error("UID cannot include /") + + // Delete current avatar directory + const userAvatarDirectory = join(avatarDirectory, uid) + await rm(userAvatarDirectory, { recursive: true, force: true }) + + if (!avatar) return {} // we don't need to set a new one + + // make a new directory + mkdir(userAvatarDirectory, { recursive: true }) + + let time: Record = {} + + // render all images and write to disk + let avatarData = await avatar.arrayBuffer() + let fileExtension = mime.getExtension(avatar.type) + for (let x of renderSizes) { + console.log(x) + try { + let start = Date.now() + let rerenderedAvatarData = await rerenderAvatar(avatarData, x) + await Bun.write( + join(userAvatarDirectory, `${x}.${fileExtension}`), + rerenderedAvatarData + ) + time[x] = Date.now()-start + } catch (e) { // clear pfp and throw if error encountered + await rm(userAvatarDirectory, { recursive: true, force: true }) + throw e + } + } + + return time } \ No newline at end of file diff --git a/src/lib/oidc.ts b/src/lib/oidc.ts index 32c7612..8bab640 100644 --- a/src/lib/oidc.ts +++ b/src/lib/oidc.ts @@ -96,7 +96,7 @@ export async function getUserInfo(id: string) { if (userInfoCache.has(tokenInfo.owner)) userInfo = userInfoCache.get(tokenInfo.owner) else { - let userInfoRequest = await fetchUserInfo(tokenInfo.token) + let userInfoRequest = await fetchUserInfo(tokenInfo.token) if (!userInfoRequest.ok) { // assume that token has expired. // try fetching a new one @@ -108,7 +108,7 @@ export async function getUserInfo(id: string) { }) if (!token) return // refresh failed. back out - prisma.token.update({ + await prisma.token.update({ where: { id }, data: { token: token.access_token, @@ -121,6 +121,21 @@ export async function getUserInfo(id: string) { } userInfo = await userInfoRequest.json() + + // update user + console.log('aaa') + await prisma.user.upsert({ + where: { + userId: userInfo.sub, + }, + update: { + identifier: userInfo[configuration.userinfo.identifier] + }, + create: { + userId: userInfo.sub, + identifier: userInfo[configuration.userinfo.identifier] + } + }) // cache userinfo userInfoCache.set(tokenInfo.owner, userInfo) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index a1c0c36..548890f 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -50,7 +50,7 @@ nav > * { display: flex; /* Flexbox fixes everything! */ } - a { + a, small { color: var(--link) } code, pre { diff --git a/src/routes/set/+page.server.ts b/src/routes/set/+page.server.ts index c750195..f01e9c2 100644 --- a/src/routes/set/+page.server.ts +++ b/src/routes/set/+page.server.ts @@ -1,5 +1,8 @@ -import {launchLogin} from "$lib/oidc" +import {getRequestUser, launchLogin} from "$lib/oidc" import configuration from "$lib/configuration.js"; +import { fail } from "@sveltejs/kit"; +import { avatarDirectory, renderSizes, setNewAvatar } from "$lib/avatars.js"; +import { join } from "path"; export async function load({ request, parent }) { const { user } = await parent(); if (!user) @@ -7,6 +10,31 @@ export async function load({ request, parent }) { return { url: request.url, - allowedImageTypes: configuration.allowed_types + allowedImageTypes: configuration.allowed_types, + renderSizes + } +} + +export const actions = { + set: async ({request, cookies}) => { + let user = await getRequestUser(request, cookies); + if (!user) + return fail(401, {error: "unauthenticated"}) + + let submission = await request.formData(); + let newAvatar = submission.get("newAvatar") + if (newAvatar !== undefined && !(newAvatar instanceof File)) + return fail(400, {success: false, error: "incorrect entry type"}) + if (!configuration.allowed_types.includes(newAvatar.type)) + return fail(400, {success: false, error: `allowed types does not include ${newAvatar.type}`}) + + let time = await setNewAvatar(user.sub, newAvatar) + + return { + success: true, + message: Object.entries(time) + .map(([res, time]) => `${res}x${res} took ${time}ms to render`) + .join("\n") + } } } \ No newline at end of file diff --git a/src/routes/set/+page.svelte b/src/routes/set/+page.svelte index d9808e9..845a132 100644 --- a/src/routes/set/+page.svelte +++ b/src/routes/set/+page.svelte @@ -2,7 +2,8 @@ import type { User } from "$lib/types"; import FilePreviewSet from "./FilePreviewSet.svelte"; - export let data: {user: User, url: string, allowedImageTypes: string[]}; + export let data: {user: User, url: string, allowedImageTypes: string[], renderSizes: number[]}; + export let form: { success: true, message: string } | { success: false, error: string } | undefined; let files: FileList; let fileSrc = `/avatar/${data.user.identifier}/` @@ -66,18 +67,30 @@ Avatar URLs...
    - {#each ["", "32", "64", "128", "256", "512"] as variant} + {#each ["", ...data.renderSizes] as variant}
  • {new URL(`/avatar/${data.user.identifier}/${variant}`, data.url)}
  • {/each}

-
+
+{#if form} + {#if form.success} +
+ Avatar set successfully +
+
{form.message}
+
+
+ {:else} + An error occurred: {form.error} + {/if} +{/if} {#key fileSrc}
diff --git a/static/default/1024.png b/static/default/1024.png new file mode 100644 index 0000000000000000000000000000000000000000..cee6e06d07deb922910f38c605ed85170cd3c9d7 GIT binary patch literal 32170 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 literal 0 HcmV?d00001