switch to sharp, dockerize
This commit is contained in:
parent
6511720e4a
commit
f72b775ee2
11
.dockerignore
Normal file
11
.dockerignore
Normal file
|
@ -0,0 +1,11 @@
|
|||
build
|
||||
.data
|
||||
node_modules
|
||||
readme
|
||||
README.md
|
||||
.npmrc
|
||||
.prettierrc
|
||||
.prettierignore
|
||||
.gitignore
|
||||
.env.example
|
||||
.svelte-kit
|
|
@ -21,4 +21,4 @@ USERINFO__IDENTIFIER=preferred_username
|
|||
ALLOWED_TYPES=image/jpg,image/jpeg,image/png,image/png,image/webp,image/gif
|
||||
|
||||
# Prisma database URL
|
||||
DATABASE_URL="file:../.data/data.db"
|
||||
DATABASE_URL=file:../.data/data.db
|
41
Dockerfile
Normal file
41
Dockerfile
Normal file
|
@ -0,0 +1,41 @@
|
|||
# skidded off https://git.madhouselabs.net/MadHouse-Labs/file-uploader/src/branch/master/Dockerfile
|
||||
FROM node:lts-alpine AS base
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
FROM oven/bun:1-debian AS base2
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
FROM base AS install
|
||||
RUN mkdir -p /temp/dev
|
||||
COPY package.json package-lock.json /temp/dev/
|
||||
RUN cd /temp/dev && npm install
|
||||
|
||||
RUN mkdir -p /temp/prod
|
||||
COPY package.json package-lock.json /temp/prod/
|
||||
RUN cd /temp/prod && npm install --omit dev
|
||||
|
||||
FROM base AS prisma
|
||||
COPY --from=install /temp/prod/node_modules node_modules
|
||||
COPY . .
|
||||
RUN npx prisma generate
|
||||
|
||||
FROM base AS prisma-dev
|
||||
COPY --from=install /temp/dev/node_modules node_modules
|
||||
COPY . .
|
||||
RUN npx prisma generate
|
||||
|
||||
FROM base2 AS build
|
||||
COPY --from=prisma-dev /usr/src/app/node_modules node_modules
|
||||
COPY . .
|
||||
# vite build
|
||||
RUN NODE_ENV=production bun --bun run build
|
||||
|
||||
FROM base2 AS release
|
||||
COPY --from=prisma /usr/src/app/prisma prisma
|
||||
COPY --from=prisma /usr/src/app/node_modules node_modules
|
||||
COPY --from=build /usr/src/app/build build
|
||||
COPY --from=build /usr/src/app/static static
|
||||
COPY --from=build /usr/src/app/package.json .
|
||||
|
||||
EXPOSE 3000/tcp
|
||||
CMD [ "bun", "run", "./build/index.js" ]
|
|
@ -1,134 +0,0 @@
|
|||
<!--
|
||||
|
||||
Creating a security policy that fits your specific local environment
|
||||
before making use of ImageMagick is highly advised. You can find guidance on
|
||||
setting up this policy at https://imagemagick.org/script/security-policy.php,
|
||||
and it's important to verify your policy using the validation tool located
|
||||
at https://imagemagick-secevaluator.doyensec.com/.
|
||||
|
||||
|
||||
Web-safe ImageMagick security policy:
|
||||
|
||||
This security protocol designed for web-safe usage focuses on situations
|
||||
where ImageMagick is applied in publicly accessible contexts, like websites.
|
||||
It deactivates the capability to read from or write to any image formats
|
||||
other than web-safe formats like GIF, JPEG, and PNG. Additionally, this
|
||||
policy prohibits the execution of image filters and indirect reads, thereby
|
||||
thwarting potential security breaches. By implementing these limitations,
|
||||
the web-safe policy fortifies the safeguarding of systems accessible to
|
||||
the public, reducing the risk of exploiting ImageMagick's capabilities
|
||||
for potential attacks.
|
||||
-->
|
||||
<policymap>
|
||||
<!-- Set maximum parallel threads. -->
|
||||
<policy domain="resource" name="thread" value="2"/>
|
||||
<!--
|
||||
Set maximum time to live in seconds or mnemonics, e.g. "2 minutes". When
|
||||
this limit is exceeded, an exception is thrown and processing stops.
|
||||
-->
|
||||
<policy domain="resource" name="time" value="60"/>
|
||||
<!--
|
||||
Set maximum number of open pixel cache files. When this limit is
|
||||
exceeded, any subsequent pixels cached to disk are closed and reopened
|
||||
on demand.
|
||||
-->
|
||||
<policy domain="resource" name="file" value="768"/>
|
||||
<!--
|
||||
Set maximum amount of memory in bytes to allocate for the pixel cache
|
||||
from the heap. When this limit is exceeded, the image pixels are cached
|
||||
to memory-mapped disk.
|
||||
-->
|
||||
<policy domain="resource" name="memory" value="256MiB"/>
|
||||
<!--
|
||||
Set maximum amount of memory map in bytes to allocate for the pixel
|
||||
cache. When this limit is exceeded, the image pixels are cached to
|
||||
disk.
|
||||
-->
|
||||
<policy domain="resource" name="map" value="512MiB"/>
|
||||
<!--
|
||||
Set the maximum width * height of an image that can reside in the pixel
|
||||
cache memory. Images that exceed the area limit are cached to disk.
|
||||
-->
|
||||
<policy domain="resource" name="area" value="16KP"/>
|
||||
<!--
|
||||
Set maximum amount of disk space in bytes permitted for use by the pixel
|
||||
cache. When this limit is exceeded, the pixel cache is not be created
|
||||
and an exception is thrown.
|
||||
-->
|
||||
<policy domain="resource" name="disk" value="1GiB"/>
|
||||
<!--
|
||||
Set the maximum length of an image sequence. When this limit is
|
||||
exceeded, an exception is thrown.
|
||||
-->
|
||||
<policy domain="resource" name="list-length" value="16"/>
|
||||
<!--
|
||||
Set the maximum width of an image. When this limit is exceeded, an
|
||||
exception is thrown.
|
||||
-->
|
||||
<policy domain="resource" name="width" value="4KP"/>
|
||||
<!--
|
||||
Set the maximum height of an image. When this limit is exceeded, an
|
||||
exception is thrown.
|
||||
-->
|
||||
<policy domain="resource" name="height" value="4KP"/>
|
||||
<!--
|
||||
Periodically yield the CPU for at least the time specified in
|
||||
milliseconds.
|
||||
-->
|
||||
<policy domain="resource" name="throttle" value="2"/>
|
||||
<!--
|
||||
Do not create temporary files in the default shared directories, instead
|
||||
specify a private area to store only ImageMagick temporary files.
|
||||
-->
|
||||
<!--
|
||||
<policy domain="resource" name="temporary-path" value="/magick/tmp/"/>
|
||||
-->
|
||||
<!--
|
||||
Force memory initialization by memory mapping select memory
|
||||
allocations.
|
||||
-->
|
||||
<policy domain="cache" name="memory-map" value="anonymous"/>
|
||||
<!--
|
||||
Ensure all image data is fully flushed and synchronized to disk.
|
||||
-->
|
||||
<policy domain="cache" name="synchronize" value="true"/>
|
||||
<!--
|
||||
Replace passphrase for secure distributed processing
|
||||
-->
|
||||
<!--
|
||||
<policy domain="cache" name="shared-secret" value="secret-passphrase" stealth="true"/>
|
||||
-->
|
||||
<!-- Do not permit any delegates to execute. -->
|
||||
<policy domain="delegate" rights="none" pattern="*"/>
|
||||
<!-- Do not permit any image filters to load. -->
|
||||
<policy domain="filter" rights="none" pattern="*"/>
|
||||
<!-- Don't read/write from/to stdin/stdout. -->
|
||||
<policy domain="path" rights="none" pattern="-"/>
|
||||
<!-- don't read sensitive paths. -->
|
||||
<policy domain="path" rights="none" pattern="/etc/*"/>
|
||||
<!-- Indirect reads are not permitted. -->
|
||||
<policy domain="path" rights="none" pattern="@*"/>
|
||||
<!--
|
||||
Deny all image modules and specifically exempt reading or writing
|
||||
web-safe image formats.
|
||||
-->
|
||||
<policy domain="module" rights="none" pattern="*"/>
|
||||
<policy domain="module" rights="read | write" pattern="{BMP,GIF,JPEG,PNG,TIFF,WEBP}"/>
|
||||
<policy domain="module" rights="read | write" pattern="{MPC}" stealth="true"/>
|
||||
<policy domain="module" rights="write" pattern="{JSON,INFO,PNM,PS}"/>
|
||||
<!--
|
||||
This policy sets the number of times to replace content of certain
|
||||
memory buffers and temporary files before they are freed or deleted.
|
||||
-->
|
||||
<policy domain="system" name="shred" value="1"/>
|
||||
<!--
|
||||
Enable the initialization of buffers with zeros, resulting in a minor
|
||||
performance penalty but with improved security.
|
||||
-->
|
||||
<policy domain="system" name="memory-map" value="anonymous"/>
|
||||
<!--
|
||||
Set the maximum amount of memory in bytes that are permitted for
|
||||
allocation requests.
|
||||
-->
|
||||
<policy domain="system" name="max-memory-request" value="256MiB"/>
|
||||
</policymap>
|
1117
package-lock.json
generated
1117
package-lock.json
generated
File diff suppressed because it is too large
Load diff
14
package.json
14
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "ava",
|
||||
"version": "1.0.1",
|
||||
"version": "1.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
|
@ -12,8 +12,6 @@
|
|||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-auto": "^3.0.0",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@types/bun": "^1.1.6",
|
||||
"prettier": "^3.1.1",
|
||||
|
@ -31,10 +29,14 @@
|
|||
"@fontsource-variable/inter": "^5.0.18",
|
||||
"@fontsource-variable/noto-sans-mono": "^5.0.20",
|
||||
"@prisma/client": "5.16.2",
|
||||
"magickwand.js": "^1.1.0",
|
||||
"mime": "^4.0.4"
|
||||
"mime": "^4.0.4",
|
||||
"sharp": "^0.33.4",
|
||||
"@sveltejs/kit": "^2.0.0"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"magickwand.js"
|
||||
"@prisma/client",
|
||||
"@prisma/engines",
|
||||
"prisma",
|
||||
"sharp"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
binaryTargets = ["native", "debian-openssl-1.1.x"]
|
||||
}
|
||||
|
||||
datasource db {
|
||||
|
|
|
@ -3,11 +3,9 @@ import { existsSync } from "node:fs"
|
|||
import { join } from "node:path"
|
||||
import { prisma } from "./clientsingleton"
|
||||
import configuration from "./configuration"
|
||||
import { Magick, MagickCore } from "magickwand.js"
|
||||
import Sharp from "sharp"
|
||||
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/"
|
||||
|
@ -37,23 +35,18 @@ export async function getPathToAvatarForIdentifier(identifier: string, size: str
|
|||
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)
|
||||
export async function rerenderAvatar(bin: ArrayBuffer, squareSize: number) {
|
||||
let img = Sharp(bin);
|
||||
let metadata = await img.metadata();
|
||||
squareSize = Math.min(...[metadata.width, metadata.height].filter(e => e) as number[], squareSize)
|
||||
|
||||
// return avatar buffer
|
||||
let tempBlob = new Magick.Blob()
|
||||
await img.writeAsync(tempBlob)
|
||||
return tempBlob.dataAsync()
|
||||
img.resize({
|
||||
width: squareSize,
|
||||
height: squareSize,
|
||||
fit: "cover"
|
||||
})
|
||||
|
||||
return img.toBuffer()
|
||||
}
|
||||
|
||||
export async function setNewAvatar(uid: string, avatar?: File) {
|
||||
|
|
Loading…
Reference in a new issue