segunolalive
segunolalive

Reputation: 175

Timing interval between GET and POST request in Node/Express

I am building a quiz website using Node/Express.

How do I ensure that users submit quiz within a specified period of time without using client-side javascript? That is, if the quiz takes 10 minutes, submission afterwards should marked as too late.

Both GET and POST requests are to the same url

Upvotes: 3

Views: 305

Answers (2)

I had the same question to solve in a evaluations app.

Here is the way I save a new date allowing to later check on server if the time is bigger than my limit when answering:

Client code:

startEvaluation: function (data) {
        return $http.put(startUrl + '/' + data._id,data);
      },

Server code:

exports.startEvaluation = function (req, res) {
  if(req.body.status==="NEW")req.body.status="STARTED";
  req.body.started=Date.now();
    Evaluation.findOneAndUpdate({_id: req.body._id}, req.body, {upsert:true , new: true }, function(err, evaluation)
    {
       if (err) {
            return handleError(res, err);
         }
         if (!evaluation) {
            return res.send(404);
         }
    });
};

Hope it helps

EDIT:

As you said are the same urls, you can use the parameter (like new for example). This way, if you answer with a NEW condition, you just call the begin method:

exports.answer = function (req, res) {
  if(req.body.status==="NEW")
  {
    req.body.status="STARTED";
    req.body.started=Date.now();
  }
  else
  {
    //Process answer here and compare another Date.now() with the stored date, and your time limit to answer
    console.log("answer");
  }

    Evaluation.findOneAndUpdate({_id: req.body._id}, req.body, {upsert:true , new: true }, function(err, evaluation)
    {
       if (err) {
            return handleError(res, err);
         }
         if (!evaluation) {
            return res.send(404);
         }
        //here is the updated evaluation with the started value.
        return res.json(200, evaluations);

    });
};

The method on the client:

 $scope.saveAnswer = function ()
            {

                if($rootScope.evaluation.status==="NEW")
                {
                    evaluationService.startEvaluation($rootScope.evaluation);
                }
                else
                {
                  //Your answer treatment
                } 

}

Anyway, a little improve on server could be done checking the test must be started to allow answering.

EDIT

Here is the code for the server to control the status of the evaluation/quiz from the backside. This allows you to mark as "outdated" the evaluations the user did not finish during the allowed 20 mins after the beginning of the quiz. Note that a setTimeout is done to leave the task on server side, waiting to reach the max time configured (20 mins in example)

function marcarNoTerminada(id, body) {      
         //later you can check the status to filter answers given after limit hour
         body.status="NOT FINISHED";
         Evaluation.findOneAndUpdate({_id: id}, body, {upsert:true , new: true }, function(err, evaluation)
    {
       console.log("Evaluacion sin finalizar");
    });
}

exports.startEvaluation = function (req, res) {
  if(req.body.status==="NEW")req.body.status="STARTED";
  req.body.started=Date.now();
  req.body.validEnd= new Date(req.body.started+(60000*20));

    var theTimer = setTimeout(function(){marcarNoTerminada(req.body._id, req.body);}, 60000*20); 
    Evaluation.findOneAndUpdate({_id: req.body._id}, req.body, {upsert:true , new: true }, function(err, evaluation)
    {
       if (err) {
            return handleError(res, err);
         }
         if (!evaluation) {
            return res.send(404);
         }

        return res.json(200, evaluation);
    });
};

Upvotes: 2

An intern has no name
An intern has no name

Reputation: 496

Dépends on the level of security and bad-connectivity-proofness you want, but what I would do is start a timer server-side when the quizz is served to the client, and reject it if the answer is submitted after a given period (10mn plus a little margin).

And to keep the client aware, you could code a client-side timer that would use as start time a value set directly in the client html by the server when serving the page.

Hope this helps !

Upvotes: 2

Related Questions