I have a simple component to verify user's email. It consists of "Send Email" (that sends email with code) button, text input to enter sent code and "Verify" button that sends code to back for verification. Berification code expires in 5 minutes. And if I resend email new code expires in 5 minutes after resend.
I'm using OnPush change detection strategy so everything is handled with async pipes. The observable wrapping "Send Email" request is passed to template as async pipe. I want to have an other observable that will emit something (e.g. true) when 5 minutes passed. Yes, I can use delay operator in the way like the following
expired$ = sendObservable$.pipe(delay(5 * 60 * 1000), mapTo(true))
But. What if user decide to resend email? How can I restart these 5 minutes from the beginging?
And yes, I understand that all of that is somewhat strange. Maybe there's totaly different way to handle expiration of code using observables and async pipes?
debounceTime delays values emitted by the source Observable, but drops
previous pending delayed emissions if a new value arrives on the
source Observable. This operator keeps track of the most recent value
from the source Observable, and emits that only when dueTime enough
time has passed without any other value appearing on the source
Observable. If a new value appears before dueTime silence occurs, the
previous value will be dropped and will not be emitted on the output
So, simply:
expired$ = sendObservable$.pipe(debounceTime(5 * 60 * 1000))
Related
I read many examples of the method in Keycloak-js without a clear explanation of the following method.
updateToken(minValidity: number): KeycloakPromise<boolean, boolean>;
Note : I am using "keycloak-js": "^15.0.2"
Here is its documentation
/**
* If the token expires within `minValidity` seconds, the token is refreshed.
* If the session status iframe is enabled, the session status is also
* checked.
* #returns A promise to set functions that can be invoked if the token is
* still valid, or if the token is no longer valid.
* #example
* ```js
* keycloak.updateToken(5).then(function(refreshed) {
* if (refreshed) {
* alert('Token was successfully refreshed');
* } else {
* alert('Token is still valid');
* }
* }).catch(function() {
* alert('Failed to refresh the token, or the session has expired');
* });
*/
I am not a native english speaker. The term "expires within" is imprecise here.
An illustration is better understood. This method updateToken periodically checks if the token is expired or not during a window of time minValidity
When the token will be refreshed ?
When the keycloak token expiration is approaching, the token refreshment is either :
right prior its expiration date within the window of time minValidity ( blue)
OR after the next period update check. (orange)
In the blue case, it makes sense to have a large enough value of minValidity.
In the orange case, a small value is better.
I understand it is the blue case.
Bonus question : What will happen if the token duration < minValidity ?
Overall you want to avoid a situation where you send the AccessToken to a server/service and it gets rejected because it's not valid anymore.
So it's a good idea to check validity everytime before using the token. As the documentation mentions: calls to a service/backend should only be made within the callback of the updateToken method. But beside that, there is no (automatic) periodic check for refreshing the token.
The minValidity comes into place if you imagine a situation where the remaining AccessToken Lifetime is only 1 second.
If you check the token on client side (isTokenExpired() => false) it will still be valid, but there is a probability, that when the request reaches a service, the token will not be valid anymore and gets rejected. => we want to avoid that
The default value for minValidity is 5 seconds. So when calling the updateToken method and the token is still valid, but will expire within the next 5 seconds the token gets refreshed and any service/backend call inside the callback will use the new token. But a call itself does not necessarily mean a new token. If the remaining lifetime is long enough, nothing happens.
So in your example the blue situation is correct. The second "update" call (if you mean a updateToken method call) will already trigger a token refresh. But again: The update calls are not done automatically. You need to either implement a periodic check or call updateToken before a backend call.
To your bonus question: I looked into the code and in a fictional situation where e.g. minValidity is 60s but a new fresh token is always only valid for 30s, a call to updateToken will trigger a refresh everytime. But imho there will be no recurring "refresh-loop"
I am creating a function on my server which is supposed to trigger daily, but not only does it not trigger as expected it triggers every time the server is reset (which it did not do yesterday). The data only needs updated once a day and rapidapi is pay per api call after 100 calls a day, so I'm really trying to get this scheduled job working.
I've only tried node-schedule on my server, which has a dependency of CRON (which is why scheduleJob is using the CRON format). Originally the function triggered as fast as my computer could refresh the server, so I know the scheduleJob is stopping the API call from being constant.
schedule.scheduleJob('* * */23 * *', function () {
console.log('Daily API call initiated.');
unirest.get("https://unogs-unogs-v1.p.rapidapi.com/aaapi.cgi?q=get:exp:US&t=ns&st=adv&p=1")
.header("X-RapidAPI-Host", "unogs-unogs-v1.p.rapidapi.com")
.header("X-RapidAPI-Key", `${keys.RICHARD_UNOGS_KEY}`)
.end(function (result) {
console.log(result.status, result.headers);
//console.log(result.body) to see all data
let data = JSON.stringify(result.body)
fs.writeFile('./movieData.json', data)
});
})
Is there a better way to write this function or achieve the desired results? I only need it triggering once per day, but my computer isn't on 24/7. Since I'm still developing the app, I don't think hosting the server on Heroku or another platform is time-efficient, but I'm more than willing to try it if it'll solve my issue.
The main goal is to tell my server to run it once a day, but to check if it was run in the last 24 hours. If it hasn't been run, run it.
ANSWERED BY jakemingolla: My CRON expression was incorrectly formatted for my intended use. * * */23 * * has the function triggering on every 23rd day (today is the 24th, +1 for index value) with no limitation or other value. That's why my function was calling constantly today. I changed my CRON expression to 15 9 * * * to trigger my API call every morning at 0915 hours.
I'm not sure your CRON format is correct based on https://crontab.guru. Based on * * */23 * *, that would correspond to "“At every minute on every 23rd day-of-month", which does not sound like what you want.
For example, the CRON string 0 0 * * * * is every day at midnight. I would update that CRON string to see if it helps alleviate the problem.
In my (express.js based) loopback app I want to schedule a task to run every 1 second. It should count every open ticket, and if they already open for a certain time, then an email should be sent. Below is a simplified code.
The problem, that 'scheduleJob' is logged, as expected, but the number of tickets is not. I think it is a context problem. How should I log the number of the found ticket? How should I communicate back from count 's callback to the schedule 's callback?
var schedule = require('node-schedule');
module.exports = function(app) {
var Ticket = app.models['Ticket']
var j = schedule.scheduleJob('* * * * * *', function(){
console.log('scheduleJob')
Ticket.count(function(err, count){
if (err) {console.log(err)}
console.log(count)
})
});
};
Do not count all the open ticket like that - It costs a lots of resources.
You should keep the number of ticket in your node.js and increase/decrease it. If you have multiple processes interacting with the database, makes one of them your master and make it handle this task.
About your problem, it seems that the library node-schedule do not support asynchronous calls.
Algorithm
At your program start, look up at the ticket in your database and retrieve the next timestamp when you should send an email.
Example, you want to send an email if a ticket is open for 1 hour, and your database have :
ticket 1 / 10 min
ticket 2 / 40 min
So your next mail should be sent in 20 min (60 min - 40 min).
use setTimeout() to wake up your node in 20 min. When you wake up, send the mail, and look at your database again for the next mail to send.
Recalcul your setTimeout if there is a new Ticket inserted in your database or If one get removed/updated.
I have an input field that updates a model via a REST api.
User writes "e"
User waits 400ms (time of the debounce)
The http call for updating the backend models fire
User quickly writes "eeeeeee"
The http call comes back with the updated model and this overwrites the current model in the frontend
The text input changes back to "e" without the user doing anything
The code I have now looks like this (RxJS 5.0.0-beta.6):
this.textInput
.valueChanges
.map(change => this.item.text = change)
.debounceTime(400)
.switchMap(
change => this.itemService.save(item)
)
.subscribe(updatedItem => this.item = updatedItem)
What I want to happen is that if the user writes more text it should cancel the previous http call even though we are still waiting for the debounce to finish.
PS: flatMapLates() was renamed to switchMap() in RxJS 5
You can use flatMapLatest operator. It is like flatMap but will unsubscribe from stream when new value arrives.
Also keep in mind that this.itemService.save(item) should return disposable that will cancel XHR request on dispose.
Here I've created jsbin for you to show how it works (Open network tab whule typing and you will see cancelled requests)
QUESTION
Using ASP.NET VB and/or JavaScript how can a user be prevented from losing form data when a session expires?
The Problem
Currently when a user is filling out form data for a period longer than the session timeout period all form data is lost on post due to session expiry.
Client side actions such as typing DO NOT reset the session timeout period.
Ideas
I would like to know ways to prevent this problem occurring.
My initial idea is a notification message warning of pending expiry
and an option to reset session timer.
An alternate idea is a way to pass a key press or mouse movement to the server to cause an auto refresh of session timer.
SOLUTION 1 : KEEP SESSION ALIVE
On way of to solve your problem is to keep session alive while the form is opened. I'm sure there many ways to 'keep alive' user's session. For me, I use generic handler and this work fine at least in my requirement.
First, create a generic handler and enter code as below:
Public Class KeepSessionAlive
Implements IHttpHandler, IRequiresSessionState
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Session("KeepSessionAlive") = DateTime.Now
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
Make sure your generic handler class implements IRequiresSessionState as above.
Then in you form page, use jQuery.post to post request the above handler at time interval of you choice. For example:
<script type="text/javascript">
$(function () {
setInterval(function () { $.post('<%= ResolveClientUrl("~/KeepSessionAlive.ashx")%>'); }, 10000); ' 10 secs interval
});
</script>
While user is on the form, the POST requests will keep refreshing user's session just like normal page requests and therefore, IIS will keep on reseting the session timeout.
SOLUTION 2 : ALERT USER BEFORE TIMEOUT
Another way is to alert user when session is about to end. This can be achieved simply by using plain javascript alone. I used this method few years back so pardon my scripting.
Create a javascript method :
function sessionTimeout(n) {
setTimeout("alertSessionTimeout()", (n - 1) * 60 * 1000);
}
function alertSessionTimeout() {
var answer = confirm("Your session is about to expire in 1 minute.\n\n
Click 'OK' to extend your session.\n
Click 'Cancel' to terminate you session immediately.");
if (answer == true)
window.location = location.href;
else {
window.top.location = 'logout.aspx';
}
}
On your form page, just enter onload script on your body tag:
<body onload="sessionTimeout(<%=session.Timeout %>)">
So, if your timeout setting is 10 minutes, user will be alerted on the 9th minute. Of course, you might want to change the code when user click OK button. My code above will refresh the page and that definitely not what you want to do, or else, user's data will be lost. You can use the generic handler as in SOLUTION 1 above to reset the session and call sessionTimeout again to reset client side timeout countdown.
In the age of single page apps if you need to work with old school approach, my advise would be to create Ajax request that constantly updates data in your website or just checks for session expiration (probably request itself would prevent that). But if it happens and you receive session expired message you could just show some login popup for user to login without leaving actual page.