mirror of
https://github.com/mollersuite/monofile.git
synced 2024-11-24 22:56:26 -08:00
🎉 bump to alpha
This commit is contained in:
parent
a5404ecc13
commit
28c066e1fc
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "monofile",
|
||||
"version": "1.3.0-pa",
|
||||
"version": "1.3.0-alpha",
|
||||
"description": "Discord-based file sharing",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as Accounts from "../lib/accounts";
|
|||
import * as auth from "../lib/auth";
|
||||
import bytes from "bytes"
|
||||
import {writeFile} from "fs";
|
||||
import { sendMail } from "../lib/mail";
|
||||
|
||||
import ServeError from "../lib/errors";
|
||||
import Files from "../lib/files";
|
||||
|
@ -67,6 +68,36 @@ adminRoutes.post("/reset", parser, (req,res) => {
|
|||
|
||||
})
|
||||
|
||||
adminRoutes.post("/elevate", parser, (req,res) => {
|
||||
|
||||
if (!auth.validate(req.cookies.auth)) {
|
||||
ServeError(res, 401, "not logged in")
|
||||
return
|
||||
}
|
||||
|
||||
let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account
|
||||
|
||||
if (!acc) return
|
||||
if (!acc.admin) return
|
||||
if (typeof req.body.target !== "string") {
|
||||
res.status(404)
|
||||
res.send()
|
||||
return
|
||||
}
|
||||
|
||||
let targetAccount = Accounts.getFromUsername(req.body.target)
|
||||
if (!targetAccount) {
|
||||
res.status(404)
|
||||
res.send()
|
||||
return
|
||||
}
|
||||
|
||||
targetAccount.admin = true;
|
||||
Accounts.save()
|
||||
res.send()
|
||||
|
||||
})
|
||||
|
||||
adminRoutes.post("/delete", parser, (req,res) => {
|
||||
|
||||
if (!auth.validate(req.cookies.auth)) {
|
||||
|
@ -100,6 +131,55 @@ adminRoutes.post("/delete", parser, (req,res) => {
|
|||
|
||||
})
|
||||
|
||||
adminRoutes.post("/delete_account", parser, async (req,res) => {
|
||||
if (!auth.validate(req.cookies.auth)) {
|
||||
ServeError(res, 401, "not logged in")
|
||||
return
|
||||
}
|
||||
|
||||
let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account
|
||||
|
||||
if (!acc) return
|
||||
if (!acc.admin) return
|
||||
if (typeof req.body.target !== "string") {
|
||||
res.status(404)
|
||||
res.send()
|
||||
return
|
||||
}
|
||||
|
||||
let targetAccount = Accounts.getFromUsername(req.body.target)
|
||||
if (!targetAccount) {
|
||||
res.status(404)
|
||||
res.send()
|
||||
return
|
||||
}
|
||||
|
||||
let accId = targetAccount.id
|
||||
|
||||
auth.AuthTokens.filter(e => e.account == accId).forEach((v) => {
|
||||
auth.invalidate(v.token)
|
||||
})
|
||||
|
||||
let cpl = () => Accounts.deleteAccount(accId).then(_ => {
|
||||
if (targetAccount?.email) {
|
||||
sendMail(targetAccount.email, "Notice of account deletion", `Your account, <span username>${targetAccount.username}</span>, has been deleted by <span username>${acc.username}</span> for the following reason: <br><br><span style="font-weight:600">${req.body.reason || "(no reason specified)"}</span><br><br> Your files ${req.body.deleteFiles ? "have been deleted" : "have not been modified"}. Thank you for using monofile.`)
|
||||
}
|
||||
res.send("account deleted")
|
||||
})
|
||||
|
||||
if (req.body.deleteFiles) {
|
||||
let f = targetAccount.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die
|
||||
for (let v of f) {
|
||||
files.unlink(v,true).catch(err => console.error(err))
|
||||
}
|
||||
|
||||
writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => {
|
||||
if (err) console.log(err)
|
||||
cpl()
|
||||
})
|
||||
} else cpl()
|
||||
})
|
||||
|
||||
adminRoutes.post("/transfer", parser, (req,res) => {
|
||||
|
||||
if (!auth.validate(req.cookies.auth)) {
|
||||
|
|
|
@ -92,7 +92,6 @@ export function delFile(optPicker) {
|
|||
]).then((exp) => {
|
||||
if (exp && exp.selected) {
|
||||
fetch(`/admin/delete`,{method:"POST", body:JSON.stringify({
|
||||
owner: exp.owner,
|
||||
target: exp.file
|
||||
})}).then((response) => {
|
||||
|
||||
|
@ -104,3 +103,91 @@ export function delFile(optPicker) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function elevateUser(optPicker) {
|
||||
optPicker.picker("Elevate user",[
|
||||
{
|
||||
name: "Username",
|
||||
icon: "/static/assets/icons/person.svg",
|
||||
id: "user",
|
||||
inputSettings: {}
|
||||
},
|
||||
{
|
||||
name: "Elevate to admin",
|
||||
icon: "/static/assets/icons/admin/update.svg",
|
||||
id: true
|
||||
}
|
||||
]).then((exp) => {
|
||||
if (exp && exp.selected) {
|
||||
fetch(`/admin/elevate`,{method:"POST", body:JSON.stringify({
|
||||
target: exp.user
|
||||
})}).then((response) => {
|
||||
|
||||
if (response.status != 200) {
|
||||
optPicker.picker(`${response.status} ${response.statusText}`,[])
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// im really lazy so i just stole this from account.js
|
||||
|
||||
export function deleteAccount(optPicker) {
|
||||
optPicker.picker("What should we do with the target account's files?",[
|
||||
{
|
||||
name: "Delete files",
|
||||
icon: "/static/assets/icons/admin/delete_file.svg",
|
||||
description: "Files will be permanently deleted",
|
||||
id: true
|
||||
},
|
||||
{
|
||||
name: "Do nothing",
|
||||
icon: "/static/assets/icons/file.svg",
|
||||
description: "Files will not be affected",
|
||||
id: false
|
||||
}
|
||||
]).then((exp) => {
|
||||
if (exp) {
|
||||
let deleteFiles = exp.selected
|
||||
|
||||
optPicker.picker(`Enter the target account's username to continue.`,[
|
||||
{
|
||||
name: "Enter account username",
|
||||
icon: "/static/assets/icons/person.svg",
|
||||
inputSettings: {},
|
||||
id:"username"
|
||||
},
|
||||
{
|
||||
name: "Optional reason",
|
||||
icon: "/static/assets/icons/more.svg",
|
||||
inputSettings: {},
|
||||
id:"reason"
|
||||
},
|
||||
{
|
||||
name: `Delete account ${deleteFiles ? "& its files" : ""}`,
|
||||
icon: "/static/assets/icons/delete_account.svg",
|
||||
description: `This cannot be undone.`,
|
||||
id: true
|
||||
}
|
||||
]).then((fin) => {
|
||||
if (fin && fin.selected) {
|
||||
fetch(`/admin/delete_account`,{method:"POST", body:JSON.stringify({
|
||||
target: fin.username,
|
||||
reason: fin.reason,
|
||||
deleteFiles
|
||||
})}).then((response) => {
|
||||
|
||||
if (response.status != 200) {
|
||||
optPicker.picker(`${response.status} ${response.statusText}`,[])
|
||||
}
|
||||
|
||||
fetchAccountData()
|
||||
})
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
|
@ -198,7 +198,7 @@
|
|||
<p>Admin</p>
|
||||
</div>
|
||||
|
||||
<button>
|
||||
<button on:click={() => admOpts.deleteAccount(optPicker)}>
|
||||
<img src="/static/assets/icons/delete_account.svg" alt="delete account">
|
||||
<p>Delete user account</p>
|
||||
</button>
|
||||
|
@ -208,7 +208,7 @@
|
|||
<p>Change user password</p>
|
||||
</button>
|
||||
|
||||
<button>
|
||||
<button on:click={() => admOpts.elevateUser(optPicker)}>
|
||||
<img src="/static/assets/icons/admin/elevate_user.svg" alt="elevate account">
|
||||
<p>Elevate account to admin</p>
|
||||
</button>
|
||||
|
@ -223,11 +223,6 @@
|
|||
<p>Delete file</p>
|
||||
</button>
|
||||
|
||||
<button>
|
||||
<img src="/static/assets/icons/update.svg" alt="update">
|
||||
<p>Update files from before monofile 1.3<span><br />This may take a while</span></p>
|
||||
</button>
|
||||
|
||||
{/if}
|
||||
<p style="font-size:12px;color:#AAAAAA;text-align:center;" class="monospace"><br />{$account.id}</p>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue