prettier 4 tabwidth

This commit is contained in:
mrfry 2022-12-10 15:34:54 +01:00
parent 00ec614f1d
commit 96b413a365
42 changed files with 7034 additions and 6905 deletions

View file

@ -46,188 +46,188 @@ let httpServer: http.Server
let httpsServer: https.Server
function GetApp(): ModuleType {
const app = express()
const app = express()
const publicDir = publicdirs[0]
if (!publicDir) {
throw new Error(`No public dir! ( API )`)
}
let domain: any = url.split('.') // [ "https://api", "frylabs", "net" ]
domain.shift() // [ "frylabs", "net" ]
domain = domain.join('.') // "frylabs.net"
logger.DebugLog(`Cookie domain: ${domain}`, 'cookie', 1)
// -------------------------------------------------------------------------------------------
app.use(
express.urlencoded({
limit: '10mb',
extended: true,
}) as RequestHandler
)
app.use(
express.json({
limit: '10mb',
}) as RequestHandler
)
app.set('view engine', 'ejs')
app.set('views', ['./src/modules/api/views', './src/sharedViews'])
app.use(
auth({
userDB: userDB,
jsonResponse: true,
exceptions: [
'/register',
'/favicon.ico',
'/login',
'/postfeedback',
'/fosuploader',
'/badtestsender',
],
})
)
app.use(
fileUpload({
limits: { fileSize: 50 * 1024 * 1024 },
})
)
// -------------------------------------------------------------------------------------------
let rootRedirectURL = ''
function reloadRootRedirectURL() {
if (utils.FileExists(rootRedirectToFile)) {
rootRedirectURL = utils.ReadFile(rootRedirectToFile)
const publicDir = publicdirs[0]
if (!publicDir) {
throw new Error(`No public dir! ( API )`)
}
}
const filesToWatch = [
{
fname: rootRedirectToFile,
logMsg: 'Root redirect URL changed',
action: reloadRootRedirectURL,
},
]
let domain: any = url.split('.') // [ "https://api", "frylabs", "net" ]
domain.shift() // [ "frylabs", "net" ]
domain = domain.join('.') // "frylabs.net"
logger.DebugLog(`Cookie domain: ${domain}`, 'cookie', 1)
function Load() {
filesToWatch.forEach((ftw) => {
if (utils.FileExists(ftw.fname)) {
utils.WatchFile(ftw.fname, () => {
logger.Log(ftw.logMsg)
ftw.action()
// -------------------------------------------------------------------------------------------
app.use(
express.urlencoded({
limit: '10mb',
extended: true,
}) as RequestHandler
)
app.use(
express.json({
limit: '10mb',
}) as RequestHandler
)
app.set('view engine', 'ejs')
app.set('views', ['./src/modules/api/views', './src/sharedViews'])
app.use(
auth({
userDB: userDB,
jsonResponse: true,
exceptions: [
'/register',
'/favicon.ico',
'/login',
'/postfeedback',
'/fosuploader',
'/badtestsender',
],
})
ftw.action()
} else {
logger.Log(
`File ${ftw.fname} does not exists to watch!`,
logger.GetColor('redbg')
)
}
})
}
)
app.use(
fileUpload({
limits: { fileSize: 50 * 1024 * 1024 },
})
)
// -------------------------------------------------------------------------------------------
Load()
let rootRedirectURL = ''
// --------------------------------------------------------------
app.get('/', function (req: Request, res: any) {
logger.LogReq(req)
if (reloadRootRedirectURL) {
res.redirect(rootRedirectURL)
} else {
res.json({ msg: 'hi c:' })
function reloadRootRedirectURL() {
if (utils.FileExists(rootRedirectToFile)) {
rootRedirectURL = utils.ReadFile(rootRedirectToFile)
}
}
})
// -------------------------------------------------------------------------------------------
const filesToWatch = [
{
fname: rootRedirectToFile,
logMsg: 'Root redirect URL changed',
action: reloadRootRedirectURL,
},
]
const submoduleDatas = setupSubModules(app)
function Load() {
filesToWatch.forEach((ftw) => {
if (utils.FileExists(ftw.fname)) {
utils.WatchFile(ftw.fname, () => {
logger.Log(ftw.logMsg)
ftw.action()
})
ftw.action()
} else {
logger.Log(
`File ${ftw.fname} does not exists to watch!`,
logger.GetColor('redbg')
)
}
})
}
// -------------------------------------------------------------------------------------------
Load()
publicdirs.forEach((pdir) => {
logger.Log(`Using public dir: ${pdir}`)
app.use(express.static(pdir))
})
// --------------------------------------------------------------
// -------------------------------------------------------------------------------------------
app.get('/', function (req: Request, res: any) {
logger.LogReq(req)
if (reloadRootRedirectURL) {
res.redirect(rootRedirectURL)
} else {
res.json({ msg: 'hi c:' })
}
})
app.get('*', function (_req: Request, res: any) {
res.status(404).render('404')
})
// -------------------------------------------------------------------------------------------
app.post('*', function (_req: Request, res: any) {
res.status(404).render('404')
})
const submoduleDatas = setupSubModules(app)
// -------------------------------------------------------------------------------------------
publicdirs.forEach((pdir) => {
logger.Log(`Using public dir: ${pdir}`)
app.use(express.static(pdir))
})
// -------------------------------------------------------------------------------------------
app.get('*', function (_req: Request, res: any) {
res.status(404).render('404')
})
app.post('*', function (_req: Request, res: any) {
res.status(404).render('404')
})
function DailyAction() {
submoduleDatas.forEach((data) => {
if (data.dailyAction) {
data.dailyAction()
}
})
}
function DailyAction() {
submoduleDatas.forEach((data) => {
if (data.dailyAction) {
data.dailyAction()
}
if (data.load) {
data.load()
}
})
}
submoduleDatas.forEach((data) => {
if (data.load) {
data.load()
return {
dailyAction: DailyAction,
app: app,
}
})
return {
dailyAction: DailyAction,
app: app,
}
}
function setupSubModules(
parentApp: express.Application,
moduleSpecificData?: any
parentApp: express.Application,
moduleSpecificData?: any
): Submodule[] {
const submoduleDir = './submodules/'
const absolutePath = __dirname + '/' + submoduleDir
if (!utils.FileExists(absolutePath)) {
return null
}
const files = utils.ReadDir(absolutePath)
const moduleDatas: Submodule[] = []
files.forEach((file) => {
if (!file.endsWith('.js')) {
return
const submoduleDir = './submodules/'
const absolutePath = __dirname + '/' + submoduleDir
if (!utils.FileExists(absolutePath)) {
return null
}
const submodulePath = submoduleDir + file
const files = utils.ReadDir(absolutePath)
const moduleDatas: Submodule[] = []
files.forEach((file) => {
if (!file.endsWith('.js')) {
return
}
const submodulePath = submoduleDir + file
try {
logger.Log(`Loading submodule '${file}' for '${moduleName}'...`)
const mod = require(submodulePath).default // eslint-disable-line
const loadedModData = mod.setup({
app: parentApp,
userDB: userDB,
url: url,
publicdirs: publicdirs,
moduleSpecificData: moduleSpecificData,
httpServer: httpServer,
httpsServer: httpsServer,
})
moduleDatas.push(loadedModData || {})
} catch (e) {
logger.Log(`Error loading submodule from ${submodulePath}`)
console.error(e)
}
})
try {
logger.Log(`Loading submodule '${file}' for '${moduleName}'...`)
const mod = require(submodulePath).default // eslint-disable-line
const loadedModData = mod.setup({
app: parentApp,
userDB: userDB,
url: url,
publicdirs: publicdirs,
moduleSpecificData: moduleSpecificData,
httpServer: httpServer,
httpsServer: httpsServer,
})
moduleDatas.push(loadedModData || {})
} catch (e) {
logger.Log(`Error loading submodule from ${submodulePath}`)
console.error(e)
}
})
return moduleDatas
return moduleDatas
}
export default {
name: moduleName,
getApp: GetApp,
setup: (data: SetupData): void => {
userDB = data.userDB
url = data.url
publicdirs = data.publicdirs
httpServer = data.httpServer
httpsServer = data.httpsServer
},
name: moduleName,
getApp: GetApp,
setup: (data: SetupData): void => {
userDB = data.userDB
url = data.url
publicdirs = data.publicdirs
httpServer = data.httpServer
httpsServer = data.httpsServer
},
}

View file

@ -19,36 +19,36 @@
------------------------------------------------------------------------- */
const DbStruct = {
msgs: {
tableStruct: {
id: {
type: 'integer',
primary: true,
autoIncrement: true,
},
sender: {
type: 'integer',
notNull: true,
},
reciever: {
type: 'integer',
notNull: true,
},
msg: {
type: 'text',
},
type: {
type: 'text',
},
date: {
type: 'integer',
},
unread: {
type: 'integer',
defaultZero: true,
},
msgs: {
tableStruct: {
id: {
type: 'integer',
primary: true,
autoIncrement: true,
},
sender: {
type: 'integer',
notNull: true,
},
reciever: {
type: 'integer',
notNull: true,
},
msg: {
type: 'text',
},
type: {
type: 'text',
},
date: {
type: 'integer',
},
unread: {
type: 'integer',
defaultZero: true,
},
},
},
},
}
export default DbStruct

View file

@ -30,65 +30,65 @@ const msgDbPath = './data/dbs/msgs.db'
const msgPaginationLimit = 15
interface ExtendedSocket extends Socket {
user: User
user: User
}
interface Message {
id: number
sender: number
reciever: number
msg: string
type: string
date: number
unread: number
id: number
sender: number
reciever: number
msg: string
type: string
date: number
unread: number
}
function setup(data: SubmoduleData): void {
const { app, httpServer, httpsServer, userDB, publicdirs } = data
const msgDB = dbtools.GetDB(msgDbPath)
const { app, httpServer, httpsServer, userDB, publicdirs } = data
const msgDB = dbtools.GetDB(msgDbPath)
const publicDir = publicdirs[0]
const uloadFiles = publicDir + 'chatFiles'
logger.Log(`Starting Socket.io Server on ${httpsServer ? 'https' : 'http'}`)
// https://socket.io/docs/v4/handling-cors/#Configuration
const io = new socket(httpsServer || httpServer, {
cors: {
credentials: true,
origin: true,
},
})
const publicDir = publicdirs[0]
const uloadFiles = publicDir + 'chatFiles'
logger.Log(`Starting Socket.io Server on ${httpsServer ? 'https' : 'http'}`)
// https://socket.io/docs/v4/handling-cors/#Configuration
const io = new socket(httpsServer || httpServer, {
cors: {
credentials: true,
origin: true,
},
})
function chatMessageRead({
sender,
reciever,
}: {
sender: number
reciever: number
}) {
dbtools.runStatement(
msgDB,
`update msgs
function chatMessageRead({
sender,
reciever,
}: {
sender: number
reciever: number
}) {
dbtools.runStatement(
msgDB,
`update msgs
set unread = 0
where sender = ${sender} and reciever = ${reciever}`,
'run'
)
io.sockets.in(sender.toString()).emit('chat message read', {
userReadMsg: reciever,
})
}
'run'
)
io.sockets.in(sender.toString()).emit('chat message read', {
userReadMsg: reciever,
})
}
io.use(socketAuth({ userDB: userDB }))
io.use(socketAuth({ userDB: userDB }))
io.on('connection', (socket: ExtendedSocket) => {
const userid = socket.user.id
io.on('connection', (socket: ExtendedSocket) => {
const userid = socket.user.id
socket.on('join', function (/*data*/) {
socket.join(userid.toString())
socket.on('join', function (/*data*/) {
socket.join(userid.toString())
const groups: number[] = dbtools
.runStatement(
msgDB,
`select * from
const groups: number[] = dbtools
.runStatement(
msgDB,
`select * from
(
select sender as a
from msgs
@ -99,172 +99,177 @@ function setup(data: SubmoduleData): void {
where sender = ${userid} or reciever = ${userid}
)t
order by t.a asc`
)
.reduce((acc: number[], x: { a: number }) => {
if (x.a !== userid) acc.push(x.a)
return acc
}, [])
)
.reduce((acc: number[], x: { a: number }) => {
if (x.a !== userid) acc.push(x.a)
return acc
}, [])
socket.emit('prev messages', {
prevMsgs: groups.map((to) => {
const first: Message = dbtools.runStatement(
msgDB,
`select * from msgs
socket.emit('prev messages', {
prevMsgs: groups.map((to) => {
const first: Message = dbtools.runStatement(
msgDB,
`select * from msgs
where sender = ${userid} and reciever = ${to} or
sender = ${to} and reciever = ${userid}
order by date desc
limit 1`
)[0]
return first
}),
})
)[0]
return first
}),
})
socket.on('get chat messages', (data) => {
const { chatPartner, from } = data
socket.on('get chat messages', (data) => {
const { chatPartner, from } = data
const msgs = dbtools.runStatement(
msgDB,
`select * from msgs
const msgs = dbtools.runStatement(
msgDB,
`select * from msgs
where (sender = ${userid} and reciever = ${chatPartner} or
sender = ${chatPartner} and reciever = ${userid})
${from ? `and date < ${from}` : ''}
order by date desc
limit ${msgPaginationLimit}`
)
)
socket.emit('get chat messages', {
requestsdMsgs: msgs,
hasMore: msgs.length === msgPaginationLimit,
socket.emit('get chat messages', {
requestsdMsgs: msgs,
hasMore: msgs.length === msgPaginationLimit,
})
// Read update
chatMessageRead({ sender: chatPartner, reciever: userid })
})
socket.on('chat message read', (data) => {
const { chatPartner } = data
chatMessageRead({ sender: chatPartner, reciever: userid })
})
socket.on(
'chat message',
(message: { reciever: string; msg: string; type: string }) => {
const { reciever, msg, type } = message
if (!reciever || !msg || !msg.trim() || !type) {
return
}
const recieverUser = dbtools.Select(userDB, 'users', {
id: reciever,
})[0]
if (!recieverUser) {
socket.emit('chat message', {
success: false,
date: new Date().getTime(),
sender: reciever,
reciever: userid,
type: 'text',
msg: `A #${reciever} számú felhasználó nem létezik`,
})
return
}
const msgObj = {
sender: userid,
reciever: parseInt(reciever),
msg: dbtools.sanitizeQuery(msg),
type: type || 'text',
date: new Date().getTime(),
unread: 1,
}
dbtools.Insert(msgDB, 'msgs', msgObj)
if (userid !== parseInt(reciever)) {
io.sockets
.in(reciever.toString())
.emit('chat message', msgObj)
}
}
)
})
// Read update
chatMessageRead({ sender: chatPartner, reciever: userid })
})
socket.on('chat message read', (data) => {
const { chatPartner } = data
chatMessageRead({ sender: chatPartner, reciever: userid })
})
socket.on(
'chat message',
(message: { reciever: string; msg: string; type: string }) => {
const { reciever, msg, type } = message
if (!reciever || !msg || !msg.trim() || !type) {
return
}
const recieverUser = dbtools.Select(userDB, 'users', {
id: reciever,
})[0]
if (!recieverUser) {
socket.emit('chat message', {
success: false,
date: new Date().getTime(),
sender: reciever,
reciever: userid,
type: 'text',
msg: `A #${reciever} számú felhasználó nem létezik`,
})
return
}
const msgObj = {
sender: userid,
reciever: parseInt(reciever),
msg: dbtools.sanitizeQuery(msg),
type: type || 'text',
date: new Date().getTime(),
unread: 1,
}
dbtools.Insert(msgDB, 'msgs', msgObj)
if (userid !== parseInt(reciever)) {
io.sockets.in(reciever.toString()).emit('chat message', msgObj)
}
}
)
// socket.on('disconnect', () => {})
// socket.on('close', () => {})
})
// socket.on('disconnect', () => {})
// socket.on('close', () => {})
})
app.post('/postchatfile', function (req: Request, res) {
logger.LogReq(req)
utils
.uploadFile(req, uloadFiles)
.then((result) => {
res.json({
success: true,
path: result.filePath.replace(publicDir, ''),
})
})
.catch(() => {
res.json({ success: false, msg: 'error during uploading' })
return
})
})
app.post('/postchatfile', function (req: Request, res) {
logger.LogReq(req)
utils
.uploadFile(req, uloadFiles)
.then((result) => {
res.json({
success: true,
path: result.filePath.replace(publicDir, ''),
})
})
.catch(() => {
res.json({ success: false, msg: 'error during uploading' })
return
})
})
app.post('/postfeedbackfile', function (req: Request, res) {
logger.LogReq(req)
const user: User = req.session.user
app.post('/postfeedbackfile', function (req: Request, res) {
logger.LogReq(req)
const user: User = req.session.user
utils
.uploadFile(req, uloadFiles)
.then(({ filePath }) => {
const fileName = filePath.replace(publicDir, '')
const isImage = ['png', 'jpg', 'jpeg', 'gif'].some((ext) => {
return fileName.toLowerCase().includes(ext)
})
const msgObj = {
sender: user.id,
reciever: 1,
msg: fileName,
type: isImage ? 'img' : 'file',
date: new Date().getTime(),
unread: 1,
}
dbtools.Insert(msgDB, 'msgs', msgObj)
utils
.uploadFile(req, uloadFiles)
.then(({ filePath }) => {
const fileName = filePath.replace(publicDir, '')
const isImage = ['png', 'jpg', 'jpeg', 'gif'].some((ext) => {
return fileName.toLowerCase().includes(ext)
})
const msgObj = {
sender: user.id,
reciever: 1,
msg: fileName,
type: isImage ? 'img' : 'file',
date: new Date().getTime(),
unread: 1,
res.json({ success: true })
io.sockets.in('1').emit('chat message', msgObj)
})
.catch(() => {
res.json({ success: false, msg: 'error during uploading' })
return
})
})
app.post(
'/postfeedback',
function (req: Request<{ content: string }>, res) {
logger.LogReq(req)
const user: User = req.session.user
const { content } = req.body
if (!content || !content.trim()) {
res.json({ success: false })
return
}
const msgObj = {
sender: user.id,
reciever: 1,
msg: dbtools.sanitizeQuery(req.body.content),
type: 'text',
date: new Date().getTime(),
unread: 1,
}
dbtools.Insert(msgDB, 'msgs', msgObj)
res.json({ success: true })
io.sockets.in('1').emit('chat message', msgObj)
}
dbtools.Insert(msgDB, 'msgs', msgObj)
)
res.json({ success: true })
io.sockets.in('1').emit('chat message', msgObj)
})
.catch(() => {
res.json({ success: false, msg: 'error during uploading' })
return
})
})
app.get('/hasNewMsg', (req: Request, res) => {
const user: User = req.session.user
const userid: number = user.id
app.post('/postfeedback', function (req: Request<{ content: string }>, res) {
logger.LogReq(req)
const user: User = req.session.user
const { content } = req.body
if (!content || !content.trim()) {
res.json({ success: false })
return
}
const msgObj = {
sender: user.id,
reciever: 1,
msg: dbtools.sanitizeQuery(req.body.content),
type: 'text',
date: new Date().getTime(),
unread: 1,
}
dbtools.Insert(msgDB, 'msgs', msgObj)
res.json({ success: true })
io.sockets.in('1').emit('chat message', msgObj)
})
app.get('/hasNewMsg', (req: Request, res) => {
const user: User = req.session.user
const userid: number = user.id
const groups = dbtools
.runStatement(
msgDB,
`select * from
const groups = dbtools
.runStatement(
msgDB,
`select * from
(
select sender as a
from msgs
@ -275,35 +280,35 @@ function setup(data: SubmoduleData): void {
where sender = ${userid} or reciever = ${userid}
)t
order by t.a asc`
)
.reduce((acc: number[], x: { a: number }) => {
if (x.a !== userid) acc.push(x.a)
return acc
}, [])
)
.reduce((acc: number[], x: { a: number }) => {
if (x.a !== userid) acc.push(x.a)
return acc
}, [])
const prevMsgs = groups.map((to: number) => {
const first = dbtools.runStatement(
msgDB,
`select * from msgs
const prevMsgs = groups.map((to: number) => {
const first = dbtools.runStatement(
msgDB,
`select * from msgs
where sender = ${userid} and reciever = ${to} or
sender = ${to} and reciever = ${userid}
order by date desc
limit 1`
)[0]
return first
})
)[0]
return first
})
res.json({
unreads: prevMsgs.reduce((acc: number[], msg: Message) => {
if (msg && msg.unread === 1 && msg.sender !== userid) {
acc.push(msg.sender)
}
return acc
}, []),
res.json({
unreads: prevMsgs.reduce((acc: number[], msg: Message) => {
if (msg && msg.unread === 1 && msg.sender !== userid) {
acc.push(msg.sender)
}
return acc
}, []),
})
})
})
}
export default {
setup: setup,
setup: setup,
}

View file

@ -26,15 +26,15 @@ import { Request, SubmoduleData } from '../../../types/basicTypes'
const uloadFiles = 'data/f'
function setup(data: SubmoduleData): void {
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
app.route('/fosuploader').post(function (req: Request, res: Response) {
utils.uploadFile(req, uloadFiles).then(({ fileName }) => {
res.redirect('/f/' + fileName)
app.route('/fosuploader').post(function (req: Request, res: Response) {
utils.uploadFile(req, uloadFiles).then(({ fileName }) => {
res.redirect('/f/' + fileName)
})
})
})
}
export default {
setup: setup,
setup: setup,
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -26,98 +26,101 @@ import type { Response } from 'express'
const quickVoteResultsDir = 'stats/qvote'
const quickVotes = 'stats/qvote/votes.json'
interface QuickVotes {
voteNames?: string[]
voteNames?: string[]
}
interface QuickVote {
votes: {
[key: string]: string
}
sum: {
[key: string]: number
}
votes: {
[key: string]: string
}
sum: {
[key: string]: number
}
}
function setup(data: SubmoduleData): void {
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
app.get('/quickvote', (req: Request, res: Response) => {
const key = req.query.key.toString()
const val: string = req.query.val
const user: User = req.session.user
app.get('/quickvote', (req: Request, res: Response) => {
const key = req.query.key.toString()
const val: string = req.query.val
const user: User = req.session.user
if (!key || !val) {
res.render('votethank', {
results: 'error',
msg: 'no key or val query param!',
})
return
}
if (!key || !val) {
res.render('votethank', {
results: 'error',
msg: 'no key or val query param!',
})
return
}
// FIXME: check vote type in file
let votes: QuickVotes = {}
if (utils.FileExists(quickVotes)) {
votes = utils.ReadJSON(quickVotes)
} else {
logger.Log(
`No such vote "${key}", and quickVotes.json is missing ( #${user.id}: ${key}-${val} )`,
logger.GetColor('blue')
)
res.render('votethank', {
result: 'no such pool',
})
return
}
// FIXME: check vote type in file
let votes: QuickVotes = {}
if (utils.FileExists(quickVotes)) {
votes = utils.ReadJSON(quickVotes)
} else {
logger.Log(
`No such vote "${key}", and quickVotes.json is missing ( #${user.id}: ${key}-${val} )`,
logger.GetColor('blue')
)
res.render('votethank', {
result: 'no such pool',
})
return
}
if (!votes.voteNames.includes(key)) {
logger.Log(
`No such vote "${key}" ( #${user.id}: ${key}-${val} )`,
logger.GetColor('blue')
)
res.render('votethank', {
result: 'no such pool',
})
return
}
if (!votes.voteNames.includes(key)) {
logger.Log(
`No such vote "${key}" ( #${user.id}: ${key}-${val} )`,
logger.GetColor('blue')
)
res.render('votethank', {
result: 'no such pool',
})
return
}
const voteFile = quickVoteResultsDir + '/' + key + '.json'
const voteFile = quickVoteResultsDir + '/' + key + '.json'
let voteData: QuickVote = {
votes: {},
sum: {},
}
let voteData: QuickVote = {
votes: {},
sum: {},
}
if (utils.FileExists(voteFile)) {
voteData = utils.ReadJSON(voteFile)
} else {
utils.CreatePath(quickVoteResultsDir)
}
if (utils.FileExists(voteFile)) {
voteData = utils.ReadJSON(voteFile)
} else {
utils.CreatePath(quickVoteResultsDir)
}
const prevVote = voteData.votes[user.id]
const prevVote = voteData.votes[user.id]
voteData.votes[user.id] = val
if (voteData.sum[val]) {
voteData.sum[val]++
} else {
voteData.sum[val] = 1
}
if (prevVote) {
if (voteData.sum[prevVote]) {
voteData.sum[prevVote] -= 1
}
}
voteData.votes[user.id] = val
if (voteData.sum[val]) {
voteData.sum[val]++
} else {
voteData.sum[val] = 1
}
if (prevVote) {
if (voteData.sum[prevVote]) {
voteData.sum[prevVote] -= 1
}
}
logger.Log(`Vote from #${user.id}: ${key}: ${val}`, logger.GetColor('blue'))
res.render('votethank', {
result: prevVote ? 'already voted' : 'success',
prevVote: prevVote,
msg: 'vote added',
logger.Log(
`Vote from #${user.id}: ${key}: ${val}`,
logger.GetColor('blue')
)
res.render('votethank', {
result: prevVote ? 'already voted' : 'success',
prevVote: prevVote,
msg: 'vote added',
})
utils.WriteFile(JSON.stringify(voteData), voteFile)
})
utils.WriteFile(JSON.stringify(voteData), voteFile)
})
}
export default {
setup: setup,
setup: setup,
}

View file

@ -23,121 +23,128 @@ import utils from '../../../utils/utils'
import { Request, SubmoduleData, User } from '../../../types/basicTypes'
interface Subjects {
[key: string]: number
[key: string]: number
}
interface IdStat {
count: number
newQuestions: number
allQuestions: number
subjs: Subjects
count: number
newQuestions: number
allQuestions: number
subjs: Subjects
}
interface IdStats {
[key: string]: IdStat
[key: string]: IdStat
}
interface IdStatWithUID extends IdStat {
userId: number
userId: number
}
const idStatFile = 'stats/idstats'
const idvStatFile = 'stats/idvstats'
function mergeObjSum(a: Subjects, b: Subjects) {
const res = { ...b }
Object.keys(a).forEach((key) => {
if (res[key]) {
res[key] += a[key]
} else {
res[key] = a[key]
}
})
const res = { ...b }
Object.keys(a).forEach((key) => {
if (res[key]) {
res[key] += a[key]
} else {
res[key] = a[key]
}
})
return res
return res
}
function setup(data: SubmoduleData): void {
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
app.get('/ranklist', (req: Request, res) => {
logger.LogReq(req)
let result: IdStats
const querySince: string = req.query.since
const user: User = req.session.user
app.get('/ranklist', (req: Request, res) => {
logger.LogReq(req)
let result: IdStats
const querySince: string = req.query.since
const user: User = req.session.user
if (!querySince) {
result = utils.ReadJSON(idStatFile)
} else {
try {
const since = new Date(querySince)
if (!(since instanceof Date) || isNaN(since.getTime())) {
throw new Error('Not a date')
}
const data = utils.ReadJSON(idvStatFile)
result = {}
Object.keys(data).forEach((key) => {
const dailyStat = data[key]
if (new Date(key) > since) {
Object.keys(dailyStat).forEach((userId) => {
const userStat = dailyStat[userId]
const uidRes = result[userId]
if (!uidRes) {
result[userId] = userStat
} else {
result[userId] = {
count: uidRes.count + userStat.count,
newQuestions: uidRes.newQuestions + userStat.newQuestions,
allQuestions: uidRes.allQuestions + userStat.allQuestions,
subjs: mergeObjSum(uidRes.subjs, userStat.subjs),
if (!querySince) {
result = utils.ReadJSON(idStatFile)
} else {
try {
const since = new Date(querySince)
if (!(since instanceof Date) || isNaN(since.getTime())) {
throw new Error('Not a date')
}
}
const data = utils.ReadJSON(idvStatFile)
result = {}
Object.keys(data).forEach((key) => {
const dailyStat = data[key]
if (new Date(key) > since) {
Object.keys(dailyStat).forEach((userId) => {
const userStat = dailyStat[userId]
const uidRes = result[userId]
if (!uidRes) {
result[userId] = userStat
} else {
result[userId] = {
count: uidRes.count + userStat.count,
newQuestions:
uidRes.newQuestions +
userStat.newQuestions,
allQuestions:
uidRes.allQuestions +
userStat.allQuestions,
subjs: mergeObjSum(
uidRes.subjs,
userStat.subjs
),
}
}
})
}
})
} catch (err) {
res.json({
msg: 'invalid date format, or other error occured',
})
}
}
const list: Array<IdStatWithUID> = []
const sum = {
count: 0,
newQuestions: 0,
allQuestions: 0,
}
Object.keys(result).forEach((key) => {
list.push({
userId: parseInt(key),
...result[key],
})
}
sum.count = sum.count + result[key].count
sum.newQuestions = sum.newQuestions + result[key].newQuestions
sum.allQuestions = sum.allQuestions + result[key].allQuestions
})
} catch (err) {
if (list.length === 0) {
res.json({
msg: 'There are no users in the stats db :c',
})
return
}
res.json({
msg: 'invalid date format, or other error occured',
since: querySince,
sum: sum,
list: list,
selfuserId: user.id,
})
}
}
const list: Array<IdStatWithUID> = []
const sum = {
count: 0,
newQuestions: 0,
allQuestions: 0,
}
Object.keys(result).forEach((key) => {
list.push({
userId: parseInt(key),
...result[key],
})
sum.count = sum.count + result[key].count
sum.newQuestions = sum.newQuestions + result[key].newQuestions
sum.allQuestions = sum.allQuestions + result[key].allQuestions
})
if (list.length === 0) {
res.json({
msg: 'There are no users in the stats db :c',
})
return
}
res.json({
since: querySince,
sum: sum,
list: list,
selfuserId: user.id,
})
})
}
export default {
setup: setup,
setup: setup,
}

View file

@ -25,110 +25,110 @@ import utils from '../../../utils/utils'
import { Request, SubmoduleData } from '../../../types/basicTypes'
interface Categories {
[key: string]: {
name: string
color: string
}
[key: string]: {
name: string
color: string
}
}
enum CardState {
TODO = 'todo',
INPROGRESS = 'inprogress',
TESTING = 'testing',
DONE = 'done',
INPROD = 'inprod',
NOTPOSSIBLE = 'notpossible',
TODO = 'todo',
INPROGRESS = 'inprogress',
TESTING = 'testing',
DONE = 'done',
INPROD = 'inprod',
NOTPOSSIBLE = 'notpossible',
}
interface Card {
id: number
name: string
description: string
category: string
points: number
state: CardState
votes: number[]
id: number
name: string
description: string
category: string
points: number
state: CardState
votes: number[]
}
type Columns = {
[key in CardState]: {
name: string
clickable: boolean
}
[key in CardState]: {
name: string
clickable: boolean
}
}
interface Groups {
[key: string]: {
name: string
description: string
}
[key: string]: {
name: string
description: string
}
}
interface Todos {
categories: Categories
cards: Card[]
columns: Columns
groups: Groups
categories: Categories
cards: Card[]
columns: Columns
groups: Groups
}
const todosFile = 'data/todos.json'
function setup(data: SubmoduleData): void {
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
const { app /* userDB, url, publicdirs, moduleSpecificData */ } = data
app.get('/voteTodo', (req: Request, res: Response) => {
logger.LogReq(req)
const userId = req.session.user.id
const id: string = req.query.id
const todos: Todos = utils.ReadJSON(todosFile)
app.get('/voteTodo', (req: Request, res: Response) => {
logger.LogReq(req)
const userId = req.session.user.id
const id: string = req.query.id
const todos: Todos = utils.ReadJSON(todosFile)
if (!id) {
res.json({
msg: 'id query undefined',
result: 'not ok',
})
}
if (!id) {
res.json({
msg: 'id query undefined',
result: 'not ok',
})
}
const cardIndex = todos.cards.findIndex((currcard) => {
return currcard.id === parseInt(id)
const cardIndex = todos.cards.findIndex((currcard) => {
return currcard.id === parseInt(id)
})
if (cardIndex === -1) {
res.json({
msg: 'card not found',
result: 'not ok',
})
return
}
const ind = todos.cards[cardIndex].votes.indexOf(userId)
if (ind === -1) {
todos.cards[cardIndex].votes.push(userId)
} else {
todos.cards[cardIndex].votes.splice(ind, 1)
}
utils.WriteFile(JSON.stringify(todos, null, 2), todosFile)
res.json({
todos: todos,
userId: userId,
msg: 'updated',
result: 'ok',
})
})
if (cardIndex === -1) {
res.json({
msg: 'card not found',
result: 'not ok',
})
return
}
const ind = todos.cards[cardIndex].votes.indexOf(userId)
if (ind === -1) {
todos.cards[cardIndex].votes.push(userId)
} else {
todos.cards[cardIndex].votes.splice(ind, 1)
}
app.get('/todos', (req: Request, res: Response) => {
logger.LogReq(req)
const userId = req.session.user.id
const todos = utils.ReadJSON(todosFile)
utils.WriteFile(JSON.stringify(todos, null, 2), todosFile)
res.json({
todos: todos,
userId: userId,
msg: 'updated',
result: 'ok',
res.json({
todos: todos,
userId: userId,
result: 'ok',
})
})
})
app.get('/todos', (req: Request, res: Response) => {
logger.LogReq(req)
const userId = req.session.user.id
const todos = utils.ReadJSON(todosFile)
res.json({
todos: todos,
userId: userId,
result: 'ok',
})
})
}
export default {
setup: setup,
setup: setup,
}

View file

@ -27,320 +27,324 @@ 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
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(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`,
if (!utils.FileExists(usersFile)) {
utils.WriteFile('{}', usersFile)
}
}
const users = utils.ReadJSON(usersFile)
return {
success: true,
files: utils.ReadDir(dir).reduce((acc, file) => {
const stat = fs.lstatSync(dir + '/' + file)
if (!utils.FileExists(dir)) {
return {
success: false,
msg: `Path '${safeSubdir}' does not exists`,
}
}
if (stat.isDirectory()) {
return acc
}
return {
success: true,
files: utils.ReadDir(dir).reduce((acc, file) => {
const stat = fs.lstatSync(dir + '/' + file)
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
}, []),
}
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
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/')) {
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)
const safePath = decodeURIComponent(req.url)
.split('?')[0]
.replace(/\.+/g, '.')
.replace(/\/+/g, '/')
if (!utils.FileExists(userFilesDir)) {
utils.CreatePath(userFilesDir, true)
}
const subdir: string = 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<{ dir: string; fname: string }>, res) => {
logger.LogReq(req)
const dir: string = req.body.dir
const fname: string = 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<{ name: string }>, res) => {
logger.LogReq(req)
const name: string = 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<{ dir: string }>, 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<{ path: string; to: string }>, 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[2]
const dir = x[1]
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
if (!data[fname].upvotes) {
data[fname].upvotes = []
}
if (!data[fname].downvotes) {
data[fname].downvotes = []
}
utils.WriteFile(JSON.stringify(data), dataFilePath)
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)
}
}
} 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: string = 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<{ dir: string; fname: string }>, res) => {
logger.LogReq(req)
const dir: string = req.body.dir
const fname: string = 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<{ name: string }>, res) => {
logger.LogReq(req)
const name: string = 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,
const result = listDir(publicDir, dir, userFilesDir)
res.json(result)
})
})
app.post('/uploadUserFile', (req: Request<{ dir: string }>, res) => {
logger.LogReq(req)
app.post('/deleteDir', (req: Request<{ name: string }>, res) => {
logger.LogReq(req)
const { name } = req.body
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
}
const safeName = name.replace(/\.+/g, '').replace(/\/+/g, '')
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<{ path: string; to: string }>, 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
if (!utils.FileExists(userFilesDir + '/' + safeName)) {
res.json({
success: false,
msg: `Dir ${name} does not exist!`,
})
return
}
utils.CreatePath(userFilesDir + '/' + safeName, true)
const result = listDir(publicDir, name, userFilesDir)
if (result.files.length === 0) {
utils.deleteDir(userFilesDir + '/' + safeName)
} else {
res.json({ succes: false, msg: `Dir ${name} is not empty!` })
return
}
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)
})
app.post('/deleteDir', (req: Request<{ name: string }>, res) => {
logger.LogReq(req)
const { name } = req.body
const safeName = name.replace(/\.+/g, '').replace(/\/+/g, '')
if (!utils.FileExists(userFilesDir + '/' + safeName)) {
res.json({
success: false,
msg: `Dir ${name} does not exist!`,
})
return
}
utils.CreatePath(userFilesDir + '/' + safeName, true)
const result = listDir(publicDir, name, userFilesDir)
if (result.files.length === 0) {
utils.deleteDir(userFilesDir + '/' + safeName)
} else {
res.json({ succes: false, msg: `Dir ${name} is not empty!` })
return
}
res.json({ succes: true })
})
res.json({ succes: true })
})
}
export default {
setup: setup,
setup: setup,
}

View file

@ -24,10 +24,10 @@ import type { Database } from 'better-sqlite3'
import logger from '../../../utils/logger'
import utils from '../../../utils/utils'
import {
Request,
SubmoduleData,
User,
Submodule,
Request,
SubmoduleData,
User,
Submodule,
} from '../../../types/basicTypes'
import dbtools from '../../../utils/dbtools'
@ -38,321 +38,322 @@ const maxPWCount = 3
const daysAfterUserGetsPWs = 7 // days after user gets pw-s
interface Session {
id: string
userId: number
createDate: string
lastAccess: string
isScript: number
id: string
userId: number
createDate: string
lastAccess: string
isScript: number
}
function BackupDB(usersDbBackupPath: string, userDB: Database) {
logger.Log('Backing up auth DB ...')
utils.CreatePath(usersDbBackupPath, true)
userDB
.backup(
`${usersDbBackupPath}/users.${utils
.GetDateString()
.replace(/ /g, '_')}.db`
)
.then(() => {
logger.Log('Auth DB backup complete!')
})
.catch((err: Error) => {
logger.Log('Auth DB backup failed!', logger.GetColor('redbg'))
console.error(err)
})
logger.Log('Backing up auth DB ...')
utils.CreatePath(usersDbBackupPath, true)
userDB
.backup(
`${usersDbBackupPath}/users.${utils
.GetDateString()
.replace(/ /g, '_')}.db`
)
.then(() => {
logger.Log('Auth DB backup complete!')
})
.catch((err: Error) => {
logger.Log('Auth DB backup failed!', logger.GetColor('redbg'))
console.error(err)
})
}
function setup(data: SubmoduleData): Submodule {
const { app, userDB, url /* publicdirs, moduleSpecificData */ } = data
let domain: any = url.split('.') // [ "https://api", "frylabs", "net" ]
domain.shift() // [ "frylabs", "net" ]
domain = domain.join('.') // "frylabs.net"
logger.DebugLog(`Cookie domain: ${domain}`, 'cookie', 1)
const { app, userDB, url /* publicdirs, moduleSpecificData */ } = data
let domain: any = url.split('.') // [ "https://api", "frylabs", "net" ]
domain.shift() // [ "frylabs", "net" ]
domain = domain.join('.') // "frylabs.net"
logger.DebugLog(`Cookie domain: ${domain}`, 'cookie', 1)
app.get('/avaiblePWS', (req: Request, res: any) => {
logger.LogReq(req)
app.get('/avaiblePWS', (req: Request, res: any) => {
logger.LogReq(req)
const user: User = req.session.user
const user: User = req.session.user
res.json({
success: true,
userCreated: user.created,
availablePWS: user.avaiblePWRequests,
requestedPWS: user.pwRequestCount,
maxPWCount: maxPWCount,
daysAfterUserGetsPWs: daysAfterUserGetsPWs,
dayDiff: getDayDiff(user.created),
userCount: dbtools.TableInfo(userDB, 'users').dataCount,
})
})
app.post('/getpw', function (req: Request, res: any) {
logger.LogReq(req)
const requestingUser = req.session.user
if (requestingUser.avaiblePWRequests <= 0) {
res.json({
result: 'error',
success: false,
msg: 'Too many passwords requested or cant request password yet, try later',
})
logger.Log(
`User #${requestingUser.id} requested too much passwords`,
logger.GetColor('cyan')
)
return
}
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: requestingUser.avaiblePWRequests - 1,
pwRequestCount: requestingUser.pwRequestCount + 1,
},
{
id: requestingUser.id,
}
)
const pw = uuidv4()
const insertRes = dbtools.Insert(userDB, 'users', {
pw: pw,
avaiblePWRequests: 0,
created: utils.GetDateString(),
createdBy: requestingUser.id,
})
logger.Log(
`User #${requestingUser.id} created new user #${insertRes.lastInsertRowid}`,
logger.GetColor('cyan')
)
res.json({
pw: pw,
success: true,
userCreated: requestingUser.created,
availablePWS: requestingUser.avaiblePWRequests,
requestedPWS: requestingUser.pwRequestCount,
maxPWCount: maxPWCount,
daysAfterUserGetsPWs: daysAfterUserGetsPWs,
dayDiff: getDayDiff(requestingUser.created),
userCount: dbtools.TableInfo(userDB, 'users').dataCount,
})
})
app.post('/login', (req: Request, res: any) => {
logger.LogReq(req)
const pw = req.body.pw
? req.body.pw.replace(/'/g, '').replace(/"/g, '').replace(/;/g, '')
: false
const isScript = req.body.script
const user: User = dbtools.Select(userDB, 'users', {
pw: pw,
})[0]
if (user) {
const sessionID = uuidv4()
const existingSessions = dbtools
.Select(userDB, 'sessions', {
userID: user.id,
isScript: isScript ? 1 : 0,
})
.sort((a: Session, b: Session) => {
return (
new Date(a.lastAccess).getTime() - new Date(b.lastAccess).getTime()
)
res.json({
success: true,
userCreated: user.created,
availablePWS: user.avaiblePWRequests,
requestedPWS: user.pwRequestCount,
maxPWCount: maxPWCount,
daysAfterUserGetsPWs: daysAfterUserGetsPWs,
dayDiff: getDayDiff(user.created),
userCount: dbtools.TableInfo(userDB, 'users').dataCount,
})
})
const diff = existingSessions.length - minimumAlowwedSessions
if (diff > 0) {
logger.Log(
`Multiple ${isScript ? 'script' : 'website'} sessions ( ${
existingSessions.length
} ) for #${user.id}, deleting olds`,
logger.GetColor('cyan')
app.post('/getpw', function (req: Request, res: any) {
logger.LogReq(req)
const requestingUser = req.session.user
if (requestingUser.avaiblePWRequests <= 0) {
res.json({
result: 'error',
success: false,
msg: 'Too many passwords requested or cant request password yet, try later',
})
logger.Log(
`User #${requestingUser.id} requested too much passwords`,
logger.GetColor('cyan')
)
return
}
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: requestingUser.avaiblePWRequests - 1,
pwRequestCount: requestingUser.pwRequestCount + 1,
},
{
id: requestingUser.id,
}
)
for (let i = 0; i < diff; i++) {
const id = existingSessions[i].id
dbtools.Delete(userDB, 'sessions', {
id: id,
isScript: isScript ? 1 : 0,
})
}
}
dbtools.Update(
userDB,
'users',
{
loginCount: user.loginCount + 1,
lastLogin: utils.GetDateString(),
},
{
id: user.id,
}
)
const pw = uuidv4()
const insertRes = dbtools.Insert(userDB, 'users', {
pw: pw,
avaiblePWRequests: 0,
created: utils.GetDateString(),
createdBy: requestingUser.id,
})
dbtools.Insert(userDB, 'sessions', {
id: sessionID,
userID: user.id,
isScript: isScript ? 1 : 0,
createDate: utils.GetDateString(),
})
// https://www.npmjs.com/package/cookie
res.cookie('sessionID', sessionID, {
domain: domain,
expires: new Date(
new Date().getTime() + 10 * 365 * 24 * 60 * 60 * 1000
),
sameSite: 'none',
secure: true,
})
res.cookie('sessionID', sessionID, {
expires: new Date(
new Date().getTime() + 10 * 365 * 24 * 60 * 60 * 1000
),
sameSite: 'none',
secure: true,
})
res.json({
result: 'success',
msg: 'you are now logged in',
})
logger.Log(
`Successfull login to ${
isScript ? 'script' : 'website'
} with user ID: #${user.id}`,
logger.GetColor('cyan')
)
} else {
logger.Log(
`Login attempt with invalid pw: ${pw} to ${
isScript ? 'script' : 'website'
}`,
logger.GetColor('cyan')
)
res.json({
result: 'error',
msg: 'Invalid password',
})
}
})
app.get('/logout', (req: Request, res: any) => {
logger.LogReq(req)
const sessionID = req.cookies.sessionID
const user: User = req.session.user
const { all } = req.query
if (!user) {
res.json({
msg: 'You are not logged in',
success: false,
})
return
}
logger.Log(
`Successfull logout with user ID: #${user.id}`,
logger.GetColor('cyan')
)
if (all) {
dbtools.Delete(userDB, 'sessions', {
userID: user.id,
})
} else {
dbtools.Delete(userDB, 'sessions', {
id: sessionID,
})
}
res.clearCookie('sessionID').json({
msg: 'Successfull logout',
result: 'success',
})
})
function getDayDiff(dateString: string | Date) {
const msdiff = new Date().getTime() - new Date(dateString).getTime()
return Math.floor(msdiff / (1000 * 3600 * 24))
}
function IncrementAvaiblePWs() {
// FIXME: check this if this is legit and works
logger.Log('Incrementing avaible PW-s ...')
const users: Array<User> = dbtools.SelectAll(userDB, 'users')
const day = new Date().getDay()
if (day === 1) {
users.forEach((user) => {
const dayDiff = getDayDiff(user.created)
if (dayDiff < daysAfterUserGetsPWs) {
logger.Log(
`User #${user.id} is not registered long enough to get password ( ${dayDiff} days, ${daysAfterUserGetsPWs} needed)`,
logger.Log(
`User #${requestingUser.id} created new user #${insertRes.lastInsertRowid}`,
logger.GetColor('cyan')
)
return
}
)
if (user.avaiblePWRequests >= maxPWCount) {
return
res.json({
pw: pw,
success: true,
userCreated: requestingUser.created,
availablePWS: requestingUser.avaiblePWRequests,
requestedPWS: requestingUser.pwRequestCount,
maxPWCount: maxPWCount,
daysAfterUserGetsPWs: daysAfterUserGetsPWs,
dayDiff: getDayDiff(requestingUser.created),
userCount: dbtools.TableInfo(userDB, 'users').dataCount,
})
})
app.post('/login', (req: Request, res: any) => {
logger.LogReq(req)
const pw = req.body.pw
? req.body.pw.replace(/'/g, '').replace(/"/g, '').replace(/;/g, '')
: false
const isScript = req.body.script
const user: User = dbtools.Select(userDB, 'users', {
pw: pw,
})[0]
if (user) {
const sessionID = uuidv4()
const existingSessions = dbtools
.Select(userDB, 'sessions', {
userID: user.id,
isScript: isScript ? 1 : 0,
})
.sort((a: Session, b: Session) => {
return (
new Date(a.lastAccess).getTime() -
new Date(b.lastAccess).getTime()
)
})
const diff = existingSessions.length - minimumAlowwedSessions
if (diff > 0) {
logger.Log(
`Multiple ${isScript ? 'script' : 'website'} sessions ( ${
existingSessions.length
} ) for #${user.id}, deleting olds`,
logger.GetColor('cyan')
)
for (let i = 0; i < diff; i++) {
const id = existingSessions[i].id
dbtools.Delete(userDB, 'sessions', {
id: id,
isScript: isScript ? 1 : 0,
})
}
}
dbtools.Update(
userDB,
'users',
{
loginCount: user.loginCount + 1,
lastLogin: utils.GetDateString(),
},
{
id: user.id,
}
)
dbtools.Insert(userDB, 'sessions', {
id: sessionID,
userID: user.id,
isScript: isScript ? 1 : 0,
createDate: utils.GetDateString(),
})
// https://www.npmjs.com/package/cookie
res.cookie('sessionID', sessionID, {
domain: domain,
expires: new Date(
new Date().getTime() + 10 * 365 * 24 * 60 * 60 * 1000
),
sameSite: 'none',
secure: true,
})
res.cookie('sessionID', sessionID, {
expires: new Date(
new Date().getTime() + 10 * 365 * 24 * 60 * 60 * 1000
),
sameSite: 'none',
secure: true,
})
res.json({
result: 'success',
msg: 'you are now logged in',
})
logger.Log(
`Successfull login to ${
isScript ? 'script' : 'website'
} with user ID: #${user.id}`,
logger.GetColor('cyan')
)
} else {
logger.Log(
`Login attempt with invalid pw: ${pw} to ${
isScript ? 'script' : 'website'
}`,
logger.GetColor('cyan')
)
res.json({
result: 'error',
msg: 'Invalid password',
})
}
})
app.get('/logout', (req: Request, res: any) => {
logger.LogReq(req)
const sessionID = req.cookies.sessionID
const user: User = req.session.user
const { all } = req.query
if (!user) {
res.json({
msg: 'You are not logged in',
success: false,
})
return
}
logger.Log(
`Setting avaible PW-s for user #${user.id}: ${user.avaiblePWRequests} -> ${maxPWCount}`,
logger.GetColor('cyan')
`Successfull logout with user ID: #${user.id}`,
logger.GetColor('cyan')
)
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: maxPWCount,
},
{
id: user.id,
}
)
})
if (all) {
dbtools.Delete(userDB, 'sessions', {
userID: user.id,
})
} else {
dbtools.Delete(userDB, 'sessions', {
id: sessionID,
})
}
res.clearCookie('sessionID').json({
msg: 'Successfull logout',
result: 'success',
})
})
function getDayDiff(dateString: string | Date) {
const msdiff = new Date().getTime() - new Date(dateString).getTime()
return Math.floor(msdiff / (1000 * 3600 * 24))
}
users.forEach((user) => {
const dayDiff = getDayDiff(user.created)
if (dayDiff === daysAfterUserGetsPWs) {
logger.Log(
`Setting avaible PW-s for user #${user.id}: ${user.avaiblePWRequests} -> ${maxPWCount}`,
logger.GetColor('cyan')
)
function IncrementAvaiblePWs() {
// FIXME: check this if this is legit and works
logger.Log('Incrementing avaible PW-s ...')
const users: Array<User> = dbtools.SelectAll(userDB, 'users')
const day = new Date().getDay()
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: maxPWCount,
},
{
id: user.id,
}
)
}
})
}
if (day === 1) {
users.forEach((user) => {
const dayDiff = getDayDiff(user.created)
if (dayDiff < daysAfterUserGetsPWs) {
logger.Log(
`User #${user.id} is not registered long enough to get password ( ${dayDiff} days, ${daysAfterUserGetsPWs} needed)`,
logger.GetColor('cyan')
)
return
}
return {
dailyAction: () => {
BackupDB(usersDbBackupPath, userDB)
IncrementAvaiblePWs()
},
}
if (user.avaiblePWRequests >= maxPWCount) {
return
}
logger.Log(
`Setting avaible PW-s for user #${user.id}: ${user.avaiblePWRequests} -> ${maxPWCount}`,
logger.GetColor('cyan')
)
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: maxPWCount,
},
{
id: user.id,
}
)
})
}
users.forEach((user) => {
const dayDiff = getDayDiff(user.created)
if (dayDiff === daysAfterUserGetsPWs) {
logger.Log(
`Setting avaible PW-s for user #${user.id}: ${user.avaiblePWRequests} -> ${maxPWCount}`,
logger.GetColor('cyan')
)
dbtools.Update(
userDB,
'users',
{
avaiblePWRequests: maxPWCount,
},
{
id: user.id,
}
)
}
})
}
return {
dailyAction: () => {
BackupDB(usersDbBackupPath, userDB)
IncrementAvaiblePWs()
},
}
}
export default {
setup: setup,
setup: setup,
}

View file

@ -19,78 +19,78 @@
------------------------------------------------------------------------- */
const DBStruct = {
users: {
tableStruct: {
id: {
type: 'integer',
primary: true,
autoIncrement: true,
},
pw: {
type: 'text',
notNull: true,
unique: true,
},
notes: {
type: 'text',
},
loginCount: {
type: 'number',
defaultZero: true,
},
created: {
type: 'text',
notNull: true,
},
lastLogin: {
type: 'text',
},
lastAccess: {
type: 'text',
},
avaiblePWRequests: {
type: 'number',
defaultZero: true,
},
pwRequestCount: {
type: 'number',
defaultZero: true,
},
createdBy: {
type: 'number',
},
users: {
tableStruct: {
id: {
type: 'integer',
primary: true,
autoIncrement: true,
},
pw: {
type: 'text',
notNull: true,
unique: true,
},
notes: {
type: 'text',
},
loginCount: {
type: 'number',
defaultZero: true,
},
created: {
type: 'text',
notNull: true,
},
lastLogin: {
type: 'text',
},
lastAccess: {
type: 'text',
},
avaiblePWRequests: {
type: 'number',
defaultZero: true,
},
pwRequestCount: {
type: 'number',
defaultZero: true,
},
createdBy: {
type: 'number',
},
},
},
},
sessions: {
foreignKey: [
{
keysFrom: ['userID'],
table: 'users',
keysTo: ['id'],
},
],
tableStruct: {
id: {
type: 'text',
primary: true,
notNull: true,
},
userID: {
type: 'number',
notNull: true,
},
createDate: {
type: 'text',
notNull: true,
},
lastAccess: {
type: 'text',
},
isScript: {
type: 'number',
notNull: true,
},
sessions: {
foreignKey: [
{
keysFrom: ['userID'],
table: 'users',
keysTo: ['id'],
},
],
tableStruct: {
id: {
type: 'text',
primary: true,
notNull: true,
},
userID: {
type: 'number',
notNull: true,
},
createDate: {
type: 'text',
notNull: true,
},
lastAccess: {
type: 'text',
},
isScript: {
type: 'number',
notNull: true,
},
},
},
},
}
export default DBStruct