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, }