mirror of
https://gitlab.com/MrFry/mrfrys-node-server
synced 2025-04-01 20:24:18 +02:00
prettier 4 tabwidth
This commit is contained in:
parent
00ec614f1d
commit
96b413a365
42 changed files with 7034 additions and 6905 deletions
|
@ -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
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue