mirror of
https://github.com/mollersuite/monofile.git
synced 2024-11-21 21:36:26 -08:00
Okay that's enough for now
This commit is contained in:
parent
e624e19802
commit
86f5727d83
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="/api/v1/account/customization/css"
|
href="/api/v1/account/me/css"
|
||||||
>
|
>
|
||||||
|
|
||||||
<link
|
<link
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
<link
|
<link
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
href="/api/v1/account/customization/css"
|
href="/api/v1/account/me/css"
|
||||||
>
|
>
|
||||||
|
|
||||||
<meta
|
<meta
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
href="/static/assets/icons/icon_temp.svg"
|
href="/static/assets/icons/icon_temp.svg"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/api/v1/account/customization/css" />
|
<link rel="stylesheet" href="/api/v1/account/me/css" />
|
||||||
|
|
||||||
<meta
|
<meta
|
||||||
name="viewport"
|
name="viewport"
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { readFile } from "fs/promises"
|
||||||
import Files from "./lib/files.js"
|
import Files from "./lib/files.js"
|
||||||
import { getAccount } from "./lib/middleware.js"
|
import { getAccount } from "./lib/middleware.js"
|
||||||
import APIRouter from "./routes/api.js"
|
import APIRouter from "./routes/api.js"
|
||||||
import preview from "./routes/preview.js"
|
import preview from "./routes/api/web/preview.js"
|
||||||
import {fileURLToPath} from "url"
|
import {fileURLToPath} from "url"
|
||||||
import {dirname} from "path"
|
import {dirname} from "path"
|
||||||
import pkg from "../../package.json" assert {type:"json"}
|
import pkg from "../../package.json" assert {type:"json"}
|
||||||
|
@ -95,10 +95,6 @@ app.get("/", async (ctx) =>
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// serve download page
|
|
||||||
|
|
||||||
app.get("/download/:fileId", getAccount, preview(files))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
routes should be in this order:
|
routes should be in this order:
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ let mailConfig = config.mail,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// lazy but
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description Sends an email
|
* @description Sends an email
|
||||||
* @param to Target email address
|
* @param to Target email address
|
||||||
|
@ -35,4 +33,4 @@ export function sendMail(to: string, subject: string, content: string) {
|
||||||
`<span style="font-family:monospace;padding:3px 5px 3px 5px;border-radius:8px;background-color:#1C1C1C;color:#DDDDDD;">`
|
`<span style="font-family:monospace;padding:3px 5px 3px 5px;border-radius:8px;background-color:#1C1C1C;color:#DDDDDD;">`
|
||||||
)}<br><br><span style="opacity:0.5">If you do not believe that you are the intended recipient of this email, please disregard this message.</span>`,
|
)}<br><br><span style="opacity:0.5">If you do not believe that you are the intended recipient of this email, please disregard this message.</span>`,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -74,7 +74,6 @@ export default class APIRouter {
|
||||||
async loadAPIMethods() {
|
async loadAPIMethods() {
|
||||||
let files = await readdir(APIDirectory)
|
let files = await readdir(APIDirectory)
|
||||||
for (let version of files) {
|
for (let version of files) {
|
||||||
/// temporary (hopefully). need to figure out something else for this
|
|
||||||
let def = JSON.parse(
|
let def = JSON.parse(
|
||||||
(
|
(
|
||||||
await readFile(
|
await readFile(
|
||||||
|
|
|
@ -31,12 +31,12 @@ export default function (files: Files) {
|
||||||
typeof body.target !== "string" ||
|
typeof body.target !== "string" ||
|
||||||
typeof body.password !== "string"
|
typeof body.password !== "string"
|
||||||
) {
|
) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetAccount = Accounts.getFromUsername(body.target)
|
let targetAccount = Accounts.getFromUsername(body.target)
|
||||||
if (!targetAccount) {
|
if (!targetAccount) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
Accounts.password.set(targetAccount.id, body.password)
|
Accounts.password.set(targetAccount.id, body.password)
|
||||||
|
@ -53,7 +53,7 @@ export default function (files: Files) {
|
||||||
`<b>Hello there!</b> This email is to notify you of a password change that an administrator, <span username>${acc.username}</span>, has initiated. You have been logged out of your devices. Thank you for using monofile.`
|
`<b>Hello there!</b> This email is to notify you of a password change that an administrator, <span username>${acc.username}</span>, has initiated. You have been logged out of your devices. Thank you for using monofile.`
|
||||||
)
|
)
|
||||||
.then(() => ctx.text("OK"))
|
.then(() => ctx.text("OK"))
|
||||||
.catch(() => ctx.status(500))
|
.catch(() => ctx.text("err while sending email", 500))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -62,12 +62,12 @@ export default function (files: Files) {
|
||||||
let acc = ctx.get("account") as Accounts.Account
|
let acc = ctx.get("account") as Accounts.Account
|
||||||
|
|
||||||
if (typeof body.target !== "string") {
|
if (typeof body.target !== "string") {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetAccount = Accounts.getFromUsername(body.target)
|
let targetAccount = Accounts.getFromUsername(body.target)
|
||||||
if (!targetAccount) {
|
if (!targetAccount) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
Accounts.save()
|
Accounts.save()
|
||||||
|
@ -77,32 +77,31 @@ export default function (files: Files) {
|
||||||
adminRoutes.post("/delete", async (ctx) => {
|
adminRoutes.post("/delete", async (ctx) => {
|
||||||
const body = await ctx.req.json()
|
const body = await ctx.req.json()
|
||||||
if (typeof body.target !== "string") {
|
if (typeof body.target !== "string") {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetFile = files.files[body.target]
|
let targetFile = files.files[body.target]
|
||||||
|
|
||||||
if (!targetFile) {
|
if (!targetFile) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
return files
|
return files
|
||||||
.unlink(body.target)
|
.unlink(body.target)
|
||||||
.then(() => ctx.status(200))
|
.then(() => ctx.text("ok", 200))
|
||||||
.catch(() => ctx.status(500))
|
.catch(() => ctx.text("err", 500))
|
||||||
.finally(() => ctx.status(200))
|
|
||||||
})
|
})
|
||||||
|
|
||||||
adminRoutes.post("/delete_account", async (ctx) => {
|
adminRoutes.post("/delete_account", async (ctx) => {
|
||||||
let acc = ctx.get("account") as Accounts.Account
|
let acc = ctx.get("account") as Accounts.Account
|
||||||
const body = await ctx.req.json()
|
const body = await ctx.req.json()
|
||||||
if (typeof body.target !== "string") {
|
if (typeof body.target !== "string") {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetAccount = Accounts.getFromUsername(body.target)
|
let targetAccount = Accounts.getFromUsername(body.target)
|
||||||
if (!targetAccount) {
|
if (!targetAccount) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let accId = targetAccount.id
|
let accId = targetAccount.id
|
||||||
|
@ -149,12 +148,12 @@ export default function (files: Files) {
|
||||||
adminRoutes.post("/transfer", async (ctx) => {
|
adminRoutes.post("/transfer", async (ctx) => {
|
||||||
const body = await ctx.req.json()
|
const body = await ctx.req.json()
|
||||||
if (typeof body.target !== "string" || typeof body.owner !== "string") {
|
if (typeof body.target !== "string" || typeof body.owner !== "string") {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetFile = files.files[body.target]
|
let targetFile = files.files[body.target]
|
||||||
if (!targetFile) {
|
if (!targetFile) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
let newOwner = Accounts.getFromUsername(body.owner || "")
|
let newOwner = Accounts.getFromUsername(body.owner || "")
|
||||||
|
@ -173,21 +172,21 @@ export default function (files: Files) {
|
||||||
}
|
}
|
||||||
targetFile.owner = newOwner ? newOwner.id : undefined
|
targetFile.owner = newOwner ? newOwner.id : undefined
|
||||||
|
|
||||||
files
|
return files
|
||||||
.write()
|
.write()
|
||||||
.then(() => ctx.status(200))
|
.then(() => ctx.text("ok", 200))
|
||||||
.catch(() => ctx.status(500))
|
.catch(() => ctx.text("error", 500))
|
||||||
})
|
})
|
||||||
|
|
||||||
adminRoutes.post("/idchange", async (ctx) => {
|
adminRoutes.post("/idchange", async (ctx) => {
|
||||||
const body = await ctx.req.json()
|
const body = await ctx.req.json()
|
||||||
if (typeof body.target !== "string" || typeof body.new !== "string") {
|
if (typeof body.target !== "string" || typeof body.new !== "string") {
|
||||||
return ctx.status(400)
|
return ctx.text("inappropriate body", 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetFile = files.files[body.target]
|
let targetFile = files.files[body.target]
|
||||||
if (!targetFile) {
|
if (!targetFile) {
|
||||||
return ctx.status(404)
|
return ctx.text("not found", 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (files.files[body.new]) {
|
if (files.files[body.new]) {
|
||||||
|
|
|
@ -105,7 +105,6 @@ export default function (files: Files) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// upload handlers
|
|
||||||
|
|
||||||
primaryApi.post(
|
primaryApi.post(
|
||||||
"/upload",
|
"/upload",
|
||||||
|
|
|
@ -33,28 +33,54 @@ type Message = [200 | 400 | 401 | 403 | 501, string]
|
||||||
|
|
||||||
// there's probably a less stupid way to do this than `K in keyof Pick<UserUpdateParameters, T>`
|
// there's probably a less stupid way to do this than `K in keyof Pick<UserUpdateParameters, T>`
|
||||||
// @Jack5079 make typings better if possible
|
// @Jack5079 make typings better if possible
|
||||||
|
|
||||||
|
type Validator<T extends keyof Partial<Accounts.Account>, ValueNotNull extends boolean> =
|
||||||
|
/**
|
||||||
|
* @param actor The account performing this action
|
||||||
|
* @param target The target account for this action
|
||||||
|
* @param params Changes being patched in by the user
|
||||||
|
*/
|
||||||
|
(actor: Accounts.Account, target: Accounts.Account, params: UserUpdateParameters & (ValueNotNull extends true ? {
|
||||||
|
[K in keyof Pick<UserUpdateParameters, T>]-? : UserUpdateParameters[K]
|
||||||
|
} : {})) => Accounts.Account[T] | Message
|
||||||
|
|
||||||
|
// this type is so stupid stg
|
||||||
|
interface ValidatorWithSettings<T extends keyof Partial<Accounts.Account>> {
|
||||||
|
acceptsNull?: boolean,
|
||||||
|
validator: Validator<T, this["acceptsNull"] extends true ? true : false> // i give upp ill fix this later
|
||||||
|
}
|
||||||
|
|
||||||
const validators: {
|
const validators: {
|
||||||
[T in keyof Partial<Accounts.Account>]:
|
[T in keyof Partial<Accounts.Account>]:
|
||||||
/**
|
Validator<T, true> | ValidatorWithSettings<T>
|
||||||
* @param actor The account performing this action
|
|
||||||
* @param target The target account for this action
|
|
||||||
* @param params Changes being patched in by the user
|
|
||||||
*/
|
|
||||||
(actor: Accounts.Account, target: Accounts.Account, params: UserUpdateParameters & {
|
|
||||||
[K in keyof Pick<UserUpdateParameters, T>]-? : UserUpdateParameters[K]
|
|
||||||
}) => Accounts.Account[T] | Message
|
|
||||||
} = {
|
} = {
|
||||||
defaultFileVisibility(actor, target, params) {
|
defaultFileVisibility(actor, target, params) {
|
||||||
if (["public", "private", "anonymous"].includes(params.defaultFileVisibility))
|
if (["public", "private", "anonymous"].includes(params.defaultFileVisibility))
|
||||||
return params.defaultFileVisibility
|
return params.defaultFileVisibility
|
||||||
else return [400, "invalid file visibility"]
|
else return [400, "invalid file visibility"]
|
||||||
},
|
},
|
||||||
email(actor, target, params) {
|
email: {
|
||||||
return [501, "not implemented"]
|
acceptsNull: true,
|
||||||
|
validator: (actor, target, params) => {
|
||||||
|
if (!params.currentPassword // actor on purpose here to allow admins
|
||||||
|
|| (params.currentPassword && Accounts.password.check(actor.id, params.currentPassword)))
|
||||||
|
return [401, "current password incorrect"]
|
||||||
|
|
||||||
|
if (!params.email) {
|
||||||
|
if (target.email) {
|
||||||
|
sendMail(
|
||||||
|
target.email,
|
||||||
|
`Email disconnected`,
|
||||||
|
`<b>Hello there!</b> Your email address (<span code>${target.email}</span>) has been disconnected from the monofile account <span username>${target.username}</span>. Thank you for using monofile.`
|
||||||
|
).catch()
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
password(actor, target, params) {
|
password(actor, target, params) {
|
||||||
if (
|
if (
|
||||||
!params.currentPassword
|
!params.currentPassword // actor on purpose here to allow admins
|
||||||
|| (params.currentPassword && Accounts.password.check(actor.id, params.currentPassword))
|
|| (params.currentPassword && Accounts.password.check(actor.id, params.currentPassword))
|
||||||
) return [401, "current password incorrect"]
|
) return [401, "current password incorrect"]
|
||||||
|
|
||||||
|
@ -77,7 +103,7 @@ const validators: {
|
||||||
|
|
||||||
},
|
},
|
||||||
username(actor, target, params) {
|
username(actor, target, params) {
|
||||||
if (!params.currentPassword
|
if (!params.currentPassword // actor on purpose here to allow admins
|
||||||
|| (params.currentPassword && Accounts.password.check(actor.id, params.currentPassword)))
|
|| (params.currentPassword && Accounts.password.check(actor.id, params.currentPassword)))
|
||||||
return [401, "current password incorrect"]
|
return [401, "current password incorrect"]
|
||||||
|
|
||||||
|
@ -106,13 +132,30 @@ const validators: {
|
||||||
return params.username
|
return params.username
|
||||||
|
|
||||||
},
|
},
|
||||||
customCSS(actor, target, params) {
|
customCSS: {
|
||||||
if (
|
acceptsNull: true,
|
||||||
!params.customCSS ||
|
validator: (actor, target, params) => {
|
||||||
(params.customCSS.match(id_check_regex)?.[0] == params.customCSS &&
|
if (
|
||||||
params.customCSS.length <= Configuration.maxUploadIdLength)
|
!params.customCSS ||
|
||||||
) return params.customCSS
|
(params.customCSS.match(id_check_regex)?.[0] == params.customCSS &&
|
||||||
else return [400, "bad file id"]
|
params.customCSS.length <= Configuration.maxUploadIdLength)
|
||||||
|
) return params.customCSS
|
||||||
|
else return [400, "bad file id"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
embed(actor, target, params) {
|
||||||
|
if (params.embed.color === undefined) {
|
||||||
|
params.embed.color = target.embed?.color
|
||||||
|
} else if (!((params.embed.color.toLowerCase().match(/[a-f0-9]+/)?.[0] ==
|
||||||
|
params.embed.color.toLowerCase() &&
|
||||||
|
params.embed.color.length == 6) || params.embed.color == null)) return [400, "bad embed color"]
|
||||||
|
|
||||||
|
|
||||||
|
if (params.embed.largeImage === undefined) {
|
||||||
|
params.embed.largeImage = target.embed?.largeImage
|
||||||
|
} else params.embed.largeImage = Boolean(params.embed.largeImage)
|
||||||
|
|
||||||
|
return params.embed
|
||||||
},
|
},
|
||||||
admin(actor, target, params) {
|
admin(actor, target, params) {
|
||||||
if (actor.admin && !target.admin) return params.admin
|
if (actor.admin && !target.admin) return params.admin
|
||||||
|
@ -217,24 +260,41 @@ export default function (files: Files) {
|
||||||
if (Array.isArray(body))
|
if (Array.isArray(body))
|
||||||
return ServeError(ctx, 400, "invalid body")
|
return ServeError(ctx, 400, "invalid body")
|
||||||
|
|
||||||
let results: [keyof Accounts.Account, Accounts.Account[keyof Accounts.Account]|Message][] = Object.entries(body).filter(e => e[1] && e[0] !== "currentPassword").map(([x]) =>
|
let results: ([keyof Accounts.Account, Accounts.Account[keyof Accounts.Account]]|Message)[] =
|
||||||
[
|
(Object.entries(body)
|
||||||
x as keyof Accounts.Account,
|
.filter(e => e[0] !== "currentPassword") as [keyof Accounts.Account, UserUpdateParameters[keyof Accounts.Account]][])
|
||||||
x in validators
|
.map(([x, v]) => {
|
||||||
? validators[x as keyof Accounts.Account]!(actor, target, body as any)
|
if (!validators[x])
|
||||||
: [400, `the ${x} parameter cannot be set or is not a valid parameter`] as Message
|
return [400, `the ${x} parameter cannot be set or is not a valid parameter`] as Message
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
let allMsgs = results.map(([x,v]) => {
|
let validator =
|
||||||
|
(typeof validators[x] == "object"
|
||||||
|
? validators[x]
|
||||||
|
: {
|
||||||
|
validator: validators[x] as Validator<typeof x, false>,
|
||||||
|
acceptsNull: false
|
||||||
|
}) as ValidatorWithSettings<typeof x>
|
||||||
|
|
||||||
|
if (!validator.acceptsNull && !v)
|
||||||
|
return [400, `the ${x} validator does not accept null values`] as Message
|
||||||
|
|
||||||
|
return [
|
||||||
|
x,
|
||||||
|
validator.validator(actor, target, body)
|
||||||
|
] as [keyof Accounts.Account, Accounts.Account[keyof Accounts.Account]]
|
||||||
|
})
|
||||||
|
|
||||||
|
let allMsgs = results.map((v) => {
|
||||||
if (isMessage(v))
|
if (isMessage(v))
|
||||||
return v
|
return v
|
||||||
target[x] = v as never // lol
|
target[v[0]] = v[1] as never // lol
|
||||||
return [200, "OK"] as Message
|
return [200, "OK"] as Message
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await Accounts.save()
|
||||||
|
|
||||||
if (allMsgs.length == 1)
|
if (allMsgs.length == 1)
|
||||||
return ctx.body(...allMsgs[0]!.reverse() as [Message[1], Message[0]]) // im sorry
|
return ctx.text(...allMsgs[0]!.reverse() as [Message[1], Message[0]]) // im sorry
|
||||||
else return ctx.json(allMsgs)
|
else return ctx.json(allMsgs)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -264,7 +324,33 @@ export default function (files: Files) {
|
||||||
return ctx.text("account deleted")
|
return ctx.text("account deleted")
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get("/:user")
|
router.get("/:user", requiresAccount, async (ctx) => {
|
||||||
|
let acc = ctx.get("target")
|
||||||
|
let sessionToken = auth.tokenFor(ctx)!
|
||||||
|
|
||||||
|
return ctx.json({
|
||||||
|
...acc,
|
||||||
|
password: undefined,
|
||||||
|
email:
|
||||||
|
auth.getType(sessionToken) == "User" ||
|
||||||
|
auth.getPermissions(sessionToken)?.includes("email")
|
||||||
|
? acc.email
|
||||||
|
: undefined,
|
||||||
|
activeSessions: auth.AuthTokens.filter(
|
||||||
|
(e) =>
|
||||||
|
e.type != "App" &&
|
||||||
|
e.account == acc.id &&
|
||||||
|
(e.expire > Date.now() || !e.expire)
|
||||||
|
).length,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
router.get("/css", async (ctx) => {
|
||||||
|
let acc = ctx.get('account')
|
||||||
|
if (acc?.customCSS)
|
||||||
|
return ctx.redirect(`/file/${acc.customCSS}`)
|
||||||
|
else return ctx.text("")
|
||||||
|
})
|
||||||
|
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import * as Accounts from "../../../lib/accounts.js"
|
||||||
import * as auth from "../../../lib/auth.js"
|
import * as auth from "../../../lib/auth.js"
|
||||||
import {
|
import {
|
||||||
getAccount,
|
getAccount,
|
||||||
|
requiresAccount
|
||||||
} from "../../../lib/middleware.js"
|
} from "../../../lib/middleware.js"
|
||||||
import ServeError from "../../../lib/errors.js"
|
import ServeError from "../../../lib/errors.js"
|
||||||
|
|
||||||
|
@ -53,6 +54,15 @@ export default function (files: Files) {
|
||||||
ctx.status(200)
|
ctx.status(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.get("/", requiresAccount, ctx => {
|
||||||
|
let sessionToken = auth.tokenFor(ctx)
|
||||||
|
return ctx.json({
|
||||||
|
expiry: auth.AuthTokens.find(
|
||||||
|
(e) => e.token == sessionToken
|
||||||
|
)?.expire,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
router.delete("/", (ctx) => {
|
router.delete("/", (ctx) => {
|
||||||
if (!auth.validate(getCookie(ctx, "auth")!)) {
|
if (!auth.validate(getCookie(ctx, "auth")!)) {
|
||||||
return ServeError(ctx, 401, "not logged in")
|
return ServeError(ctx, 401, "not logged in")
|
||||||
|
|
7
src/server/routes/api/web/api.json
Normal file
7
src/server/routes/api/web/api.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"name": "web",
|
||||||
|
"baseURL": "/",
|
||||||
|
"mount": [
|
||||||
|
{ "file": "preview", "to": "/download" }
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,13 +1,18 @@
|
||||||
import fs from "fs/promises"
|
import fs from "fs/promises"
|
||||||
import bytes from "bytes"
|
import bytes from "bytes"
|
||||||
import ServeError from "../lib/errors.js"
|
import ServeError from "../../../lib/errors.js"
|
||||||
import * as Accounts from "../lib/accounts.js"
|
import * as Accounts from "../../../lib/accounts.js"
|
||||||
import type { Handler } from "hono"
|
import type Files from "../../../lib/files.js"
|
||||||
import type Files from "../lib/files.js"
|
import pkg from "../../../../../package.json" assert {type:"json"}
|
||||||
import pkg from "../../../package.json" assert {type:"json"}
|
import { Hono } from "hono"
|
||||||
|
export let router = new Hono<{
|
||||||
|
Variables: {
|
||||||
|
account: Accounts.Account
|
||||||
|
}
|
||||||
|
}>()
|
||||||
|
|
||||||
export default (files: Files): Handler =>
|
export default function (files: Files) {
|
||||||
async (ctx) => {
|
router.get("/:fileId", async (ctx) => {
|
||||||
let acc = ctx.get("account") as Accounts.Account
|
let acc = ctx.get("account") as Accounts.Account
|
||||||
const fileId = ctx.req.param("fileId")
|
const fileId = ctx.req.param("fileId")
|
||||||
const host = ctx.req.header("Host")
|
const host = ctx.req.header("Host")
|
||||||
|
@ -104,4 +109,7 @@ export default (files: Files): Handler =>
|
||||||
} else {
|
} else {
|
||||||
ServeError(ctx, 404, "file not found")
|
ServeError(ctx, 404, "file not found")
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
|
return router
|
||||||
|
}
|
Loading…
Reference in a new issue