Files
mrfrys-node-server/src/modules/api/submodules/userFiles.ts
T
2022-03-20 11:49:05 +01:00

299 lines
7.6 KiB
TypeScript

import fs from 'fs'
import logger from '../../../utils/logger'
import utils from '../../../utils/utils'
import { Request, SubmoduleData, User } from '../../../types/basicTypes'
const dataFileName = '.data.json'
function listDir(publicDir: string, subdir: string, userFilesDir: string) {
const safeSubdir = subdir.replace(/\.+/g, '').replace(/\/+/g, '')
const dir = userFilesDir + '/' + safeSubdir
const usersFile = dir + '/' + dataFileName
if (!utils.FileExists(dir)) {
return {
success: false,
msg: `Directory ${subdir} does not exists`,
}
}
if (!utils.FileExists(usersFile)) {
utils.WriteFile('{}', usersFile)
}
const users = utils.ReadJSON(usersFile)
if (!utils.FileExists(dir)) {
return {
success: false,
msg: `Path '${safeSubdir}' does not exists`,
}
}
return {
success: true,
files: utils.ReadDir(dir).reduce((acc, file) => {
const stat = fs.lstatSync(dir + '/' + file)
if (stat.isDirectory()) {
return acc
}
acc.push({
name: file,
path: dir.replace(publicDir, '') + '/' + file,
size: stat.size,
date: stat.mtime.getTime(),
user: users && users[file] ? users[file].uid : -1,
views:
users && users[file] && users[file].views ? users[file].views : 0,
upvotes:
users && users[file] && users[file].upvotes
? users[file].upvotes
: [],
downvotes:
users && users[file] && users[file].downvotes
? users[file].downvotes
: [],
})
return acc
}, []),
}
}
function setup(data: SubmoduleData): void {
const { app, /* userDB, url, */ publicdirs /* moduleSpecificData */ } = data
app.use((req: Request, _res, next) => {
// /userFiles/test/2021-04-28_10-59.png
try {
if (req.url.includes('/userFiles/')) {
logger.LogReq(req)
const safePath = decodeURIComponent(req.url)
.split('?')[0]
.replace(/\.+/g, '.')
.replace(/\/+/g, '/')
const x = safePath.split('/')
const dir = x[2]
const fname = x.pop()
const dataFilePath = userFilesDir + '/' + dir + '/' + dataFileName
const data = utils.ReadJSON(dataFilePath)
if (data[fname]) {
if (!data[fname].views) {
data[fname].views = 0
}
data[fname].views = data[fname].views + 1
utils.WriteFile(JSON.stringify(data), dataFilePath)
}
}
} catch (e) {
console.error(e)
logger.Log(
`Error trying to update view count on ${req.url}`,
logger.GetColor('redbg')
)
}
next()
})
const publicDir = publicdirs[0]
const userFilesDir = publicDir + 'userFiles'
if (!utils.FileExists(userFilesDir)) {
utils.CreatePath(userFilesDir, true)
}
app.get('/listUserDir', (req: Request, res) => {
logger.LogReq(req)
if (!utils.FileExists(userFilesDir)) {
utils.CreatePath(userFilesDir, true)
}
const subdir: any = req.query.subdir
if (subdir) {
const result = listDir(publicDir, subdir, userFilesDir)
res.json(result)
} else {
res.json({
success: true,
dirs: utils.ReadDir(userFilesDir).reduce((acc, file) => {
const stat = fs.lstatSync(userFilesDir + '/' + file)
if (!stat.isDirectory()) {
return acc
}
acc.push({
name: file,
date: stat.mtime.getTime(),
size: utils.ReadDir(userFilesDir + '/' + file).length,
})
return acc
}, []),
})
}
})
app.post('/deleteUserFile', (req: Request, res) => {
logger.LogReq(req)
const dir: any = req.body.dir
const fname: any = req.body.fname
if (!dir || !fname) {
res.json({
success: false,
msg: `'dir' or 'fname' is undefined!`,
})
return
}
const safeDir = dir.replace(/\.+/g, '').replace(/\/+/g, '')
const safeFname = fname.replace(/\.+/g, '.').replace(/\/+/g, '')
const filePath = userFilesDir + '/' + safeDir + '/' + safeFname
if (!utils.FileExists(filePath)) {
res.json({
success: false,
msg: `path does not exists!`,
})
return
}
utils.deleteFile(filePath)
const usersFile = userFilesDir + '/' + safeDir + '/' + dataFileName
const users = utils.ReadJSON(usersFile)
delete users[safeFname]
utils.WriteFile(JSON.stringify(users), usersFile)
res.json({
success: true,
})
})
app.post('/newUserDir', (req: Request, res) => {
logger.LogReq(req)
const name: any = req.body.name
if (!name) {
res.json({
success: false,
msg: `name is undefined!`,
})
return
}
const safeName = name.replace(/\.+/g, '').replace(/\/+/g, '')
if (utils.FileExists(userFilesDir + '/' + safeName)) {
res.json({
success: false,
msg: `Dir ${name} already exists`,
})
return
}
utils.CreatePath(userFilesDir + '/' + safeName, true)
res.json({
success: true,
})
})
app.post('/uploadUserFile', (req: Request, res) => {
logger.LogReq(req)
const user: User = req.session.user
const dir = req.body.dir
if (!dir) {
res.json({
success: false,
msg: `dir '${dir}' is undefined!`,
})
return
}
const safeDir = dir.replace(/\.+/g, '.').replace(/\/+/g, '/')
if (!utils.FileExists(userFilesDir + '/' + safeDir)) {
res.json({
success: false,
msg: `dir '${dir}' does not exists!`,
})
return
}
utils
.uploadFile(req, userFilesDir + '/' + safeDir)
.then((body) => {
logger.Log(
`Successfull upload ${body.filePath}`,
logger.GetColor('blue')
)
const usersFile = userFilesDir + '/' + safeDir + '/' + dataFileName
const users = utils.ReadJSON(usersFile)
users[body.fileName] = { uid: user.id }
utils.WriteFile(JSON.stringify(users), usersFile)
res.json({
success: true,
})
})
.catch(() => {
res.json({ success: false, msg: 'something bad happened :s' })
})
})
app.post('/voteFile', (req: Request, res) => {
logger.LogReq(req)
const user: User = req.session.user
// { path: 'userFiles/test/2021-04-28_10-59.png', to: 'up' } 19
const { path, to } = req.body
const safePath = path.replace(/\.+/g, '.').replace(/\/+/g, '/')
const x = safePath.split('/')
const dir = x[1]
const fname = x.pop()
const dataFilePath = userFilesDir + '/' + dir + '/' + dataFileName
const data = utils.ReadJSON(dataFilePath)
if (data[fname]) {
if (!data[fname].upvotes) {
data[fname].upvotes = []
}
if (!data[fname].downvotes) {
data[fname].downvotes = []
}
const removeVote = (from: number[], uid: number) => {
if (!from.includes(uid)) {
return from
}
return from.reduce((acc, id) => {
if (id !== uid) {
acc = [...acc, id]
}
return acc
}, [])
}
data[fname].downvotes = removeVote(data[fname].downvotes, user.id)
data[fname].upvotes = removeVote(data[fname].upvotes, user.id)
if (to === 'up') {
data[fname].upvotes = [...data[fname].upvotes, user.id]
} else if (to === 'down') {
data[fname].downvotes = [...data[fname].downvotes, user.id]
} else if (to === 'clear') {
// ... already cleared
}
utils.WriteFile(JSON.stringify(data), dataFilePath)
}
const result = listDir(publicDir, dir, userFilesDir)
res.json(result)
})
}
export default {
setup: setup,
}