mirror of
https://github.com/mollersuite/monofile.git
synced 2024-11-21 21:36:26 -08:00
this hurts
This commit is contained in:
parent
fd4441633e
commit
971ee31d73
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -9,7 +9,7 @@
|
|||
"version": "1.4.0-dev",
|
||||
"license": "Unlicense",
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.2.0",
|
||||
"@hono/node-server": "^1.8.2",
|
||||
"@types/body-parser": "^1.19.2",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/multer": "^1.4.7",
|
||||
|
@ -21,7 +21,6 @@
|
|||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.0.2",
|
||||
"express": "^4.18.1",
|
||||
"form-data": "^4.0.0",
|
||||
"hono": "^3.8.3",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
|
@ -395,11 +394,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.2.0.tgz",
|
||||
"integrity": "sha512-aHT8lDMLpd7ioXJ1/057+h+oE/k7rCOWmjklYDsE0jE4CoNB9XzG4f8dRHvw4s5HJFocaYDiGgYM/V0kYbQ0ww==",
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.8.2.tgz",
|
||||
"integrity": "sha512-h8l2TBLCPHZBUrrkosZ6L5CpBLj6zdESyF4B+zngiCDF7aZFQJ0alVbLx7jn8PCVi9EyoFf8a4hOZFi1tD95EA==",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
"node": ">=18.14.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
|
@ -2135,9 +2134,9 @@
|
|||
"optional": true
|
||||
},
|
||||
"@hono/node-server": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.2.0.tgz",
|
||||
"integrity": "sha512-aHT8lDMLpd7ioXJ1/057+h+oE/k7rCOWmjklYDsE0jE4CoNB9XzG4f8dRHvw4s5HJFocaYDiGgYM/V0kYbQ0ww=="
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.8.2.tgz",
|
||||
"integrity": "sha512-h8l2TBLCPHZBUrrkosZ6L5CpBLj6zdESyF4B+zngiCDF7aZFQJ0alVbLx7jn8PCVi9EyoFf8a4hOZFi1tD95EA=="
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"node": ">=v16.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.2.0",
|
||||
"@hono/node-server": "^1.8.2",
|
||||
"@types/body-parser": "^1.19.2",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/multer": "^1.4.7",
|
||||
|
@ -30,7 +30,6 @@
|
|||
"cookie-parser": "^1.4.6",
|
||||
"dotenv": "^16.0.2",
|
||||
"express": "^4.18.1",
|
||||
"form-data": "^4.0.0",
|
||||
"hono": "^3.8.3",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"node-fetch": "^3.3.2",
|
||||
|
|
|
@ -172,9 +172,10 @@ export class UploadStream extends Writable {
|
|||
|
||||
_destroy(error: Error | null) {
|
||||
this.error = error || undefined
|
||||
|
||||
this.abort()
|
||||
/*
|
||||
if (error instanceof WebError) return // destroyed by self
|
||||
if (error) this.abort() // destroyed externally...
|
||||
if (error) return // destroyed externally...*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -182,7 +183,11 @@ export class UploadStream extends Writable {
|
|||
*/
|
||||
async abort() {
|
||||
if (!this.destroyed) this.destroy()
|
||||
if (this.current) this.current.destroy(this.error)
|
||||
await this.files.api.deleteMessages(this.messages)
|
||||
if (this.uploadId) {
|
||||
delete this.files.locks[this.uploadId]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -222,6 +227,7 @@ export class UploadStream extends Writable {
|
|||
}
|
||||
|
||||
await this.files.write()
|
||||
delete this.files.locks[this.uploadId!]
|
||||
return this.uploadId
|
||||
}
|
||||
|
||||
|
@ -257,11 +263,10 @@ export class UploadStream extends Writable {
|
|||
if (this.files.files[id] && this.files.files[id].owner != this.owner)
|
||||
return this.destroy( new WebError(403, "you don't own this file") )
|
||||
|
||||
if (false /* check if locked here */)
|
||||
if (this.files.locks[id])
|
||||
return this.destroy( new WebError(409, "a file with this ID is already being uploaded") )
|
||||
|
||||
/* lock the id */
|
||||
|
||||
this.files.locks[id] = true
|
||||
this.uploadId = id
|
||||
return this
|
||||
}
|
||||
|
@ -325,6 +330,8 @@ export default class Files {
|
|||
files: { [key: string]: FilePointer } = {}
|
||||
data_directory: string = `${process.cwd()}/.data`
|
||||
|
||||
locks: Record<string, boolean> = {} // I'll, like, do something more proper later
|
||||
|
||||
constructor(config: Configuration) {
|
||||
this.config = config
|
||||
this.api = new API(process.env.TOKEN!, config)
|
||||
|
|
46
src/server/lib/formdata.ts
Normal file
46
src/server/lib/formdata.ts
Normal file
|
@ -0,0 +1,46 @@
|
|||
import { Transform, Duplex } from "node:stream";
|
||||
import { TransformCallback } from "stream";
|
||||
|
||||
let content_disposition_matcher = /\s*([^=;]+)(?:=(?:"((?:\\"|[^"])*)"|([^;]*))?;?|;?)/g // probably a bad regex but IDC
|
||||
|
||||
export type Headers = {
|
||||
["content-disposition"]?: (string|{key: string, value: string})[],
|
||||
["content-type"]?: string
|
||||
}
|
||||
|
||||
export class Field extends Duplex {
|
||||
|
||||
headers: Headers = {}
|
||||
|
||||
constructor(unparsedHeaders: string) {
|
||||
super()
|
||||
this.headers = Object.fromEntries(
|
||||
unparsedHeaders.split("\r\n")
|
||||
.map(e => [e.split(":")[0].trim(), e.split(":").slice(1).join(":").trim()])
|
||||
)
|
||||
|
||||
if (this.headers["content-disposition"])
|
||||
this.headers["content-disposition"] = Array.from(
|
||||
(this.headers["content-disposition"] as unknown as string)
|
||||
.matchAll(content_disposition_matcher)).map(e => e[2] ? {key: e[1], value: e[2]} : e[1])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default class FormDataParser extends Transform {
|
||||
|
||||
readableObjectMode = true
|
||||
|
||||
boundary: string
|
||||
internalBuffer: Buffer | undefined
|
||||
|
||||
constructor(boundary: string) {
|
||||
super()
|
||||
this.boundary = boundary
|
||||
}
|
||||
|
||||
_transform(chunk: any, encoding: BufferEncoding, callback: TransformCallback): void {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,8 +5,8 @@ import * as Accounts from "../../../lib/accounts.js"
|
|||
import * as auth from "../../../lib/auth.js"
|
||||
import RangeParser, { type Range } from "range-parser"
|
||||
import ServeError from "../../../lib/errors.js"
|
||||
import Files from "../../../lib/files.js"
|
||||
import { getAccount } from "../../../lib/middleware.js"
|
||||
import Files, { WebError } from "../../../lib/files.js"
|
||||
import { getAccount, requiresPermissions } from "../../../lib/middleware.js"
|
||||
import {Readable} from "node:stream"
|
||||
export let primaryApi = new Hono<{
|
||||
Variables: {
|
||||
|
@ -27,8 +27,7 @@ export default function (files: Files) {
|
|||
let file = files.files[fileId]
|
||||
ctx.header("Access-Control-Allow-Origin", "*")
|
||||
ctx.header("Content-Security-Policy", "sandbox allow-scripts")
|
||||
if (ctx.req.query("attachment") == "1")
|
||||
ctx.header("Content-Disposition", "attachment")
|
||||
ctx.header("Content-Disposition", `${ctx.req.query("attachment") == "1" ? "attachment" : "inline"}; filename="${file.filename.replaceAll("\n","\\n")}"`)
|
||||
|
||||
if (file) {
|
||||
if (file.visibility == "private") {
|
||||
|
@ -91,89 +90,26 @@ export default function (files: Files) {
|
|||
}
|
||||
}
|
||||
)
|
||||
|
||||
// primaryApi.head(
|
||||
// ["/file/:fileId", "/cpt/:fileId/*", "/:fileId"],
|
||||
// async (ctx) => {
|
||||
// let file = files.files[req.params.fileId]
|
||||
|
||||
// if (
|
||||
// file.visibility == "private" &&
|
||||
// (ctx.get("account")?.id != file.owner ||
|
||||
// (auth.getType(auth.tokenFor(ctx)!) == "App" &&
|
||||
// auth
|
||||
// .getPermissions(auth.tokenFor(ctx)!)
|
||||
// ?.includes("private")))
|
||||
// ) {
|
||||
// return ctx.status(403)
|
||||
// }
|
||||
|
||||
// ctx.header("Content-Security-Policy", "sandbox allow-scripts")
|
||||
|
||||
// if (ctx.req.query("attachment") == "1")
|
||||
// ctx.header("Content-Disposition", "attachment")
|
||||
|
||||
// if (!file) {
|
||||
// res.status(404)
|
||||
// res.send()
|
||||
// } else {
|
||||
// ctx.header("Content-Type", file.mime)
|
||||
// if (file.sizeInBytes) {
|
||||
// ctx.header("Content-Length", file.sizeInBytes)
|
||||
// }
|
||||
// if (file.chunkSize) {
|
||||
// ctx.header("Accept-Ranges", "bytes")
|
||||
// }
|
||||
// res.send()
|
||||
// }
|
||||
// }
|
||||
// )
|
||||
|
||||
// upload handlers
|
||||
|
||||
/*
|
||||
primaryApi.post(
|
||||
"/upload",
|
||||
requiresPermissions("upload"),
|
||||
multerSetup.single("file"),
|
||||
async (ctx) => {
|
||||
let acc = ctx.get("account") as Accounts.Account
|
||||
|
||||
if (req.file) {
|
||||
try {
|
||||
let prm = req.header("monofile-params")
|
||||
let params: { [key: string]: any } = {}
|
||||
if (prm) {
|
||||
params = JSON.parse(prm)
|
||||
if (!ctx.req.header("Content-Type")?.startsWith("multipart/form-data")) {
|
||||
ctx.status(400)
|
||||
return ctx.body("[err] must be multipart/form-data")
|
||||
}
|
||||
|
||||
files
|
||||
.uploadFile(
|
||||
{
|
||||
owner: acc?.id,
|
||||
|
||||
uploadId: params.uploadId,
|
||||
filename: req.file.originalname,
|
||||
mime: req.file.mimetype,
|
||||
},
|
||||
req.file.buffer
|
||||
)
|
||||
.then((uID) => res.send(uID))
|
||||
.catch((stat) => {
|
||||
res.status(stat.status)
|
||||
res.send(`[err] ${stat.message}`)
|
||||
})
|
||||
} catch {
|
||||
res.status(400)
|
||||
res.send("[err] bad request")
|
||||
}
|
||||
} else {
|
||||
res.status(400)
|
||||
res.send("[err] bad request")
|
||||
if (!ctx.req.raw.body) {
|
||||
ctx.status(400)
|
||||
return ctx.body("[err] body must be supplied")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
primaryApi.post(
|
||||
"/clone",
|
||||
requiresPermissions("upload"),
|
||||
|
|
Loading…
Reference in a new issue