mirror of
https://gitlab.com/MrFry/mrfrys-node-server
synced 2025-04-01 20:24:18 +02:00
dataeditor api endpoints
This commit is contained in:
parent
3e4fda9974
commit
5ca0abbabf
8 changed files with 373 additions and 116 deletions
|
@ -37,6 +37,7 @@ import {
|
|||
shouldSearchDataFile,
|
||||
loadJSON,
|
||||
Result,
|
||||
isQuestionValid,
|
||||
} from '../../utils/actions'
|
||||
import dbtools from '../../utils/dbtools'
|
||||
import auth from '../../middlewares/auth.middleware'
|
||||
|
@ -58,7 +59,6 @@ import {
|
|||
|
||||
// files
|
||||
const msgFile = 'stats/msgs'
|
||||
const passwordFile = 'data/dataEditorPasswords.json'
|
||||
const dataEditsLog = 'stats/dataEdits'
|
||||
const dailyDataCountFile = 'stats/dailyDataCount'
|
||||
const usersDbBackupPath = 'data/dbs/backup'
|
||||
|
@ -262,8 +262,7 @@ function GetApp(): ModuleType {
|
|||
// -------------------------------------------------------------
|
||||
|
||||
app.get('/getDbs', (req: Request, res: any) => {
|
||||
logger.LogReq(req)
|
||||
|
||||
// logger.LogReq(req)
|
||||
res.json(
|
||||
questionDbs.map((qdb) => {
|
||||
return {
|
||||
|
@ -824,114 +823,6 @@ function GetApp(): ModuleType {
|
|||
})
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
// API
|
||||
|
||||
app.post('/uploaddata', (req: Request, res: any) => {
|
||||
// body: JSON.stringify({
|
||||
// newData: data,
|
||||
// count: getCount(data),
|
||||
// initialCount: initialCount,
|
||||
// password: password,
|
||||
// editedQuestions: editedQuestions
|
||||
// })
|
||||
|
||||
const {
|
||||
count,
|
||||
initialCount,
|
||||
editedQuestions,
|
||||
password /*, newData*/,
|
||||
} = req.body
|
||||
const respStatuses = {
|
||||
invalidPass: 'invalidPass',
|
||||
ok: 'ok',
|
||||
error: 'error',
|
||||
}
|
||||
|
||||
logger.LogReq(req)
|
||||
|
||||
try {
|
||||
// finding user
|
||||
const pwds = JSON.parse(utils.ReadFile(passwordFile))
|
||||
const userKey = Object.keys(pwds).find((key) => {
|
||||
const userKey = pwds[key]
|
||||
return userKey.password === password
|
||||
})
|
||||
// FIXME: check user type in dataeditorPW-s json
|
||||
const user: any = pwds[userKey]
|
||||
|
||||
// logging and stuff
|
||||
logger.Log(`Data upload`, logger.GetColor('bluebg'))
|
||||
logger.Log(`PWD: ${password}`, logger.GetColor('bluebg'))
|
||||
// returning if user password is not ok
|
||||
if (!user) {
|
||||
logger.Log(
|
||||
`Data upload: invalid password ${password}`,
|
||||
logger.GetColor('red')
|
||||
)
|
||||
utils.AppendToFile(
|
||||
utils.GetDateString() +
|
||||
'\n' +
|
||||
password +
|
||||
'(FAILED PASSWORD)\n' +
|
||||
JSON.stringify(editedQuestions) +
|
||||
'\n\n',
|
||||
dataEditsLog
|
||||
)
|
||||
res.json({ status: respStatuses.invalidPass })
|
||||
return
|
||||
}
|
||||
|
||||
logger.Log(
|
||||
`Password accepted for ${user.name}`,
|
||||
logger.GetColor('bluebg')
|
||||
)
|
||||
logger.Log(
|
||||
`Old Subjects/Questions: ${initialCount.subjectCount} / ${
|
||||
initialCount.questionCount
|
||||
} | New: ${count.subjectCount} / ${
|
||||
count.questionCount
|
||||
} | Edited question count: ${Object.keys(editedQuestions).length}`,
|
||||
logger.GetColor('bluebg')
|
||||
)
|
||||
// saving detailed editedCount
|
||||
utils.AppendToFile(
|
||||
utils.GetDateString() +
|
||||
'\n' +
|
||||
JSON.stringify(user) +
|
||||
'\n' +
|
||||
JSON.stringify(editedQuestions) +
|
||||
'\n\n',
|
||||
dataEditsLog
|
||||
)
|
||||
|
||||
// making backup
|
||||
// TODO
|
||||
// utils.CopyFile(
|
||||
// './' + dataFile,
|
||||
// `./publicDirs/qminingPublic/backs/data_before_${
|
||||
// user.name
|
||||
// }_${utils.GetDateString().replace(/ /g, '_')}`
|
||||
// ) // TODO: rewrite to dinamyc public!!!
|
||||
// logger.Log('Backup made')
|
||||
// // writing data
|
||||
// utils.WriteFile(JSON.stringify(newData), dataFile)
|
||||
// logger.Log('New data file written')
|
||||
// // reloading data file
|
||||
// data = [...newData]
|
||||
// data = newData
|
||||
logger.Log('Data set to newData')
|
||||
|
||||
res.json({
|
||||
status: respStatuses.ok,
|
||||
user: user.name,
|
||||
})
|
||||
logger.Log('Data updating done!', logger.GetColor('bluebg'))
|
||||
} catch (error) {
|
||||
logger.Log(`Data upload error! `, logger.GetColor('redbg'))
|
||||
console.error(error)
|
||||
res.json({ status: respStatuses.error, msg: error.message })
|
||||
}
|
||||
})
|
||||
|
||||
function getNewQdb(location, maxIndex) {
|
||||
logger.Log(
|
||||
|
@ -1069,6 +960,10 @@ function GetApp(): ModuleType {
|
|||
|
||||
function saveQuestion(questions, subj, testUrl, userid) {
|
||||
// TODO: clear folder every now and then, check if saved questions exist
|
||||
if (!subj) {
|
||||
logger.Log('No subj name to save test question')
|
||||
return
|
||||
}
|
||||
const questionsToSave = {
|
||||
questions: questions,
|
||||
subj: subj,
|
||||
|
@ -1077,7 +972,7 @@ function GetApp(): ModuleType {
|
|||
date: new Date(),
|
||||
}
|
||||
const fname = `${utils.GetDateString()}_${userid}_${testUrl}.json`
|
||||
const subject = getSubjNameWithoutYear(subj)
|
||||
const subject = getSubjNameWithoutYear(subj).replace(/\//g, '-')
|
||||
const subjPath = `${savedQuestionsDir}/${subject}`
|
||||
const savedSubjQuestionsFilePath = `${subjPath}/${savedQuestionsFileName}`
|
||||
|
||||
|
@ -1451,6 +1346,354 @@ function GetApp(): ModuleType {
|
|||
res.json({ msg: 'done' })
|
||||
})
|
||||
|
||||
app.get('/possibleAnswers', (req: Request, res: any) => {
|
||||
logger.LogReq(req)
|
||||
const files = utils.ReadDir(savedQuestionsDir)
|
||||
|
||||
files.sort(function(a, b) {
|
||||
return (
|
||||
fs.statSync(savedQuestionsDir + '/' + b).mtime.getTime() -
|
||||
fs.statSync(savedQuestionsDir + '/' + a).mtime.getTime()
|
||||
)
|
||||
})
|
||||
|
||||
res.json({
|
||||
savedQuestionsFileName: savedQuestionsFileName,
|
||||
subjects: files.map((subj) => {
|
||||
return {
|
||||
name: subj,
|
||||
path: `savedQuestions/${subj}/`,
|
||||
}
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
app.post('/rmPossibleAnswer', (req: Request, res: any) => {
|
||||
logger.LogReq(req)
|
||||
const user: User = req.session.user
|
||||
|
||||
const subj = req.body.subj
|
||||
const file = req.body.file
|
||||
const savedQuestionsPath = `${savedQuestionsDir}/${subj}/${savedQuestionsFileName}`
|
||||
const savedQuestions = utils.ReadJSON(savedQuestionsPath)
|
||||
let path = `${savedQuestionsDir}/${subj}/${file}`
|
||||
// to prevent deleting ../../../ ... /etc/shadow
|
||||
while (path.includes('..')) {
|
||||
path = path.replace(/\.\./g, '.')
|
||||
}
|
||||
|
||||
if (utils.FileExists(path)) {
|
||||
utils.deleteFile(path)
|
||||
|
||||
utils.WriteFile(
|
||||
JSON.stringify(
|
||||
savedQuestions.filter((sq) => {
|
||||
return sq.fname !== file
|
||||
})
|
||||
),
|
||||
savedQuestionsPath
|
||||
)
|
||||
|
||||
logger.Log(
|
||||
`User #${user.id} deleted '${file}' from subject '${subj}'`,
|
||||
logger.GetColor('cyanbg')
|
||||
)
|
||||
res.json({
|
||||
res: 'ok',
|
||||
})
|
||||
} else {
|
||||
logger.Log(
|
||||
`User #${user.id} tried to delete '${file}' from subject '${subj}', but failed`,
|
||||
logger.GetColor('red')
|
||||
)
|
||||
res.json({
|
||||
res: 'fail',
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
app.post('/updateQuestion', (req: Request, res) => {
|
||||
logger.LogReq(req)
|
||||
const user: User = req.session.user
|
||||
const date = utils.GetDateString()
|
||||
let saveDb = false
|
||||
|
||||
const editType = req.body.type
|
||||
const selectedDb = req.body.selectedDb
|
||||
if (!editType || !selectedDb) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: 'No .editType or .selectedDb !',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const dbIndex = questionDbs.findIndex((qdb) => {
|
||||
return qdb.name === selectedDb.name
|
||||
})
|
||||
const currDb = questionDbs[dbIndex]
|
||||
|
||||
if (dbIndex === -1) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: `No question db named like ${selectedDb.name}!`,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// {
|
||||
// "index": 0,
|
||||
// "subjName": "VHDL programozás",
|
||||
// "type": "delete",
|
||||
// "selectedDb": {
|
||||
// "path": "questionDbs/elearning.uni-obuda.hu.json",
|
||||
// "name": "elearning.uni-obuda.hu"
|
||||
// }
|
||||
// }
|
||||
if (editType === 'delete') {
|
||||
const { index, subjName } = req.body
|
||||
let deletedQuestion = {}
|
||||
if (isNaN(index) || !subjName) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: 'No .index or .subjName !',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
questionDbs[dbIndex].data = currDb.data.map((subj) => {
|
||||
if (subj.Name !== subjName) {
|
||||
return subj
|
||||
} else {
|
||||
return {
|
||||
...subj,
|
||||
Questions: subj.Questions.filter((question, i) => {
|
||||
if (index === i) {
|
||||
deletedQuestion = question
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.Log(
|
||||
`User #${user.id} deleted a question from '${subjName}'`,
|
||||
logger.GetColor('cyanbg')
|
||||
)
|
||||
utils.AppendToFile(
|
||||
`${date}: User ${user.id} deleted a question from '${subjName}' (index: ${index})`,
|
||||
dataEditsLog
|
||||
)
|
||||
utils.AppendToFile(JSON.stringify(deletedQuestion, null, 2), dataEditsLog)
|
||||
saveDb = true
|
||||
}
|
||||
|
||||
// {
|
||||
// "index": 0,
|
||||
// "subjName": "Elektronika",
|
||||
// "type": "edit",
|
||||
// "newVal": {
|
||||
// "Q": "Analóg műszer esetén az érzékenység az a legkisebb mennyiség, amely a műszer kijelzőjén meghatározott mértékű változást okoz.",
|
||||
// "A": "Igaz",
|
||||
// "data": {
|
||||
// "type": "simple",
|
||||
// "possibleAnswers": [
|
||||
// "Igaz"
|
||||
// ]
|
||||
// },
|
||||
// "possibleAnswers": [
|
||||
// "Igaz"
|
||||
// ]
|
||||
// },
|
||||
// "selectedDb": {
|
||||
// "path": "questionDbs/elearning.uni-obuda.hu.json",
|
||||
// "name": "elearning.uni-obuda.hu"
|
||||
// }
|
||||
// }
|
||||
if (editType === 'edit') {
|
||||
const { index, subjName, newVal } = req.body
|
||||
let oldVal = {}
|
||||
if (isNaN(index) || !subjName) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: 'No .index or .subjName !',
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!isQuestionValid(newVal)) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: 'edited question is not valid',
|
||||
question: newVal,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
questionDbs[dbIndex].data = currDb.data.map((subj) => {
|
||||
if (subj.Name !== subjName) {
|
||||
return subj
|
||||
} else {
|
||||
return {
|
||||
...subj,
|
||||
Questions: subj.Questions.map((question, i) => {
|
||||
if (index === i) {
|
||||
oldVal = question
|
||||
return newVal
|
||||
} else {
|
||||
return question
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.Log(
|
||||
`User #${user.id} edited a question in '${subjName}'`,
|
||||
logger.GetColor('cyanbg')
|
||||
)
|
||||
utils.AppendToFile(
|
||||
`${date}: User ${user.id} edited a question in '${subjName}' (index: ${index})`,
|
||||
dataEditsLog
|
||||
)
|
||||
utils.AppendToFile(
|
||||
JSON.stringify(
|
||||
{
|
||||
newVal: newVal,
|
||||
oldVal: oldVal,
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
dataEditsLog
|
||||
)
|
||||
saveDb = true
|
||||
}
|
||||
|
||||
// {
|
||||
// "subjName": "Elektronika",
|
||||
// "changedQuestions": [
|
||||
// {
|
||||
// "index": 1,
|
||||
// "value": {
|
||||
// "Q": "A műszer pontosságát a hibájával fejezzük ki, melyet az osztályjel (osztálypontosság ) mutat meg.",
|
||||
// "A": "Hamis",
|
||||
// "data": {
|
||||
// "type": "simple",
|
||||
// "possibleAnswers": [
|
||||
// "Igaz",
|
||||
// "Hamis"
|
||||
// ]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// ],
|
||||
// "deletedQuestions": [
|
||||
// 0
|
||||
// ],
|
||||
// "type": "subjEdit",
|
||||
// "selectedDb": {
|
||||
// "path": "questionDbs/elearning.uni-obuda.hu.json",
|
||||
// "name": "elearning.uni-obuda.hu"
|
||||
// }
|
||||
// }
|
||||
if (editType === 'subjEdit') {
|
||||
const { subjName, changedQuestions, deletedQuestions } = req.body
|
||||
const deletedQuestionsToWrite = []
|
||||
const changedQuestionsToWrite = []
|
||||
if (
|
||||
!Array.isArray(changedQuestions) ||
|
||||
!Array.isArray(deletedQuestions)
|
||||
) {
|
||||
res.json({
|
||||
status: 'fail',
|
||||
msg: 'no changedQuestions or deletedQuestions!',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// processing changed questions
|
||||
questionDbs[dbIndex].data = currDb.data.map((subj) => {
|
||||
if (subj.Name !== subjName) {
|
||||
return subj
|
||||
} else {
|
||||
return {
|
||||
...subj,
|
||||
Questions: subj.Questions.map((question, i) => {
|
||||
const changedTo = changedQuestions.find((cq) => {
|
||||
return cq.index === i
|
||||
})
|
||||
if (changedTo) {
|
||||
changedQuestionsToWrite.push({
|
||||
oldVal: question,
|
||||
newVal: changedTo.value,
|
||||
})
|
||||
return changedTo.value
|
||||
} else {
|
||||
return question
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// processing deletedQuestions
|
||||
questionDbs[dbIndex].data = currDb.data.map((subj) => {
|
||||
if (subj.Name !== subjName) {
|
||||
return subj
|
||||
} else {
|
||||
return {
|
||||
...subj,
|
||||
Questions: subj.Questions.filter((question, i) => {
|
||||
const isDeleted = deletedQuestions.includes(i)
|
||||
if (isDeleted) {
|
||||
deletedQuestionsToWrite.push(question)
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}),
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
logger.Log(
|
||||
`User #${user.id} modified '${subjName}'. Edited: ${deletedQuestionsToWrite.length}, deleted: ${deletedQuestionsToWrite.length}`,
|
||||
logger.GetColor('cyanbg')
|
||||
)
|
||||
utils.AppendToFile(
|
||||
`${date} User #${user.id} modified '${subjName}'. Edited: ${deletedQuestionsToWrite.length}, deleted: ${deletedQuestionsToWrite.length}`,
|
||||
dataEditsLog
|
||||
)
|
||||
utils.AppendToFile(
|
||||
JSON.stringify(
|
||||
{
|
||||
deletedQuestions: deletedQuestionsToWrite,
|
||||
changedQuestions: changedQuestionsToWrite,
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
dataEditsLog
|
||||
)
|
||||
saveDb = true
|
||||
}
|
||||
|
||||
if (saveDb) {
|
||||
utils.WriteFile(JSON.stringify(currDb.data), currDb.path)
|
||||
msgAllWorker({
|
||||
qdbs: questionDbs,
|
||||
type: 'update',
|
||||
})
|
||||
}
|
||||
|
||||
res.json({
|
||||
status: 'OK',
|
||||
})
|
||||
})
|
||||
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
app.get('*', function(req: Request, res: any) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue