Kick out the user automatically when the same account logs in again? - java

Thanks for all your replies! Here is my code! Please give your comments!
I created a column to save the present status of USER
ShareHelper.USER = nhanVien;//use static variable to save USER
if (ShareHelper.USER.getStatus() == 0) {//first login -> change status from 0 to 1
DialogHelper.alert(this, "Đăng nhập thành công!");
nvd.updateStatus(1, nhanVien.getMaNV());
this.dispose();
EduSys edu = new EduSys();
edu.setVisible(true);
} else if (ShareHelper.USER.getStatus() == 1) { //if someone logged before -> allow to login again
DialogHelper.alert(this, "Đăng nhập thành công!");
EduSys edu = new EduSys();
edu.setVisible(true);
nvd.updateStatus(2, nhanVien.getMaNV());//then update status to 2
this.dispose();
}
And in MainFrame I use a thread to update the status consecutively
Thread t1 = new Thread(new Runnable() {//use Thread to check if status change to 2-> someone logs in with same account
#Override
public void run() {
while (true) {
model.NhanVien nhanVien = nvd.findById(ShareHelper.USER.getMaNV());
ShareHelper.USER = nhanVien;
if (ShareHelper.USER.getStatus() == 2) {
DialogHelper.alert(EduSys.this, "Có người đã đăng nhập tài khoản này!");
ShareHelper.logoff();//log out the present session
nvd.updateStatus(1, ShareHelper.USER.getMaNV());//change status to 1 again
EduSys.this.dispose();
dn.setVisible(true);
}
}
}
});
t1.start();
But I got a trouble! When I log in the second time, I got kicked in both previous session and present session because Status has been changed to 2 by previous session then present session receives that value too. Can someone please help me to fix this! Thank you in advance!

You can have a Simple approach. First create application level simple cache(a simple has map will work) which will maintain the status of the user. If the user Loggs in for first time create entry for the User with the Logged in value (i.e USER -> 1) .and Update the Field accordingly in DB.
Now if the user tries to log in again Check in map for the entry if its already logged-in change the value in map as well as DB and kill all the session of that user
Thanks
TG

Related

Work around for Alexa Custom Skill Reoccuring response

I am building a custom Alexa skill
In which I can ask the name of User and repeat it. (Working fine).
Now, the next part is to confirm the name of the user.
Alexa: "Please confirm your name!"<br>
User:"-"
Alexa: "Please confirm your name!"<br>
User: "No"
Alexa: "Please confirm your name!"<br>
**User: "Yes I confirm"**
End.
Now I am trying to achieve the above behaviour, as
Alexa should prompt "Please confirm your name!" on every 10 seconds until the user Responds
"Yes, I confirm".
I have checked the API documentation but not able to find any Intent related to this case.
Please share some info or solution.
Repromting every 10 seconds when the user doesn't responds, not sure if we can do.
But we can achieve the Yes/No part. One way of doing this is by using the state. Here in this example, I am using the node-cache module for state management.
Consider the below intent named "ConfirmationQuestionIntent". It sets the state to "confirm-name".
const ConfirmationQuestionIntentHandler = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "ConfirmationQuestionIntent"
);
},
handle(handlerInput) {
const speechText = "Please confirm your name as 'John'.";
myCache.set('state','confirm-name');
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
Now, enable/Add two BuiltIn intents, AMAZON.YesIntent and AMAZON.NoIntent.
Consider the AMAZON.NoIntent below,
In the handler function. it checks if there is any state with the name "confirm-name". If it is present, it responds with "Please confirm your name as 'John'." and if not then responds with the default response.
const NoBuiltInIntent = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "AMAZON.NoIntent"
);
},
handle(handlerInput) {
const state = myCache.get("state");
let speechText = "I didn't get this!. Could you please rephrase.";
if(state === "confirm-name") speechText = "Please confirm your name as 'John'.";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
Consider the AMAZON.YesIntent below,
In the handle function, it checks if there is any state named "confirm-name". If it is, then it responds back with "Thanks for the confirmation" and deletes the state from the cache. If not then it asks the user to rephrase.
const YesBuiltInIntent = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "AMAZON.YesIntent"
);
},
handle(handlerInput) {
const state = myCache.get("state");
let speechText = "I didn't get this!. Could you please rephrase.";
if(state === "confirm-name") speechText = "Thanks for the confirmation.";
myCache.del('state');
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(speechText)
.getResponse();
}
};
So, you can use "State" to identify in which scenario the user is responding to and then provide the right response.
I am afraid it is not possible to make Alexa ask the question every 10 seconds untill the user confirm.
I suppose you are using confirmSlotDirective to confirm the name of the user.
confirmSlotDirective or simply any confirmation directive in Alexa works with words that only agree or disagree with the confirmation message. e.g. YES/NO
Solution:
1) If you have already asked for the name of the user (e.g. 'John'), do not ask it again. Simply make Alexa to say:
Alexa: "Your name is John, right?" Or "You said John? please confirm?"
User: can say Yes/No to confirm.
Note: Alexa only recognizes a limited set of international names.
2) Better way to get user's name is using Alexa's Customer Profile Api, so you won't have to worry about Alexa not able to recognize name let alone the confirmation of user's name.

Synchronize REST endpoint to wait for 2 calls with same parameter

I am creating an application in which two players should have an opportunity to compete with each other in writing code.
For example, for now one player can initiate a session creation:
#PostMapping("/prepareSession")
public UUID prepareSession(#RequestParam("taskName") String taskName) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
User playerOne = userService.findOne(currentPrincipalName);
Task task = taskService.findOne(taskName);
UUID sessionId = UUID.randomUUID();
sessionService.save(new Session(sessionId, playerOne, null, task));
return sessionId;
}
Then, this session id he needs to send to a player who he wants to compete.
And then second player inputs sessionId and gets a task description.
#GetMapping("/connect")
public Task connect(#RequestParam("sessionId") String sessionId) throws InterruptedException {
Session session = sessionService.findOne(sessionId);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
User playerSecond = userService.findOne(currentPrincipalName);
session.setPlayerSecond(playerSecond);
sessionService.save(session);
return session.getTask();
}
I wonder how to make the rest endpoint to wait until both players with same sessionId calls it and then notify them with the task description.
I want them to write code within a one session, with a one code timer.
Please suggest how I should do that
What you are looking for can be achieve like this
You could use a DeferredResult result and store it in a map until a user with the same sessionId joins. Ex
Map<String, DeferredResult<ResponseEntity<?>>> unconnected = new HashMap<String, DeferredResult<ResponseEntity<?>>>();
User one would call the connect prepareSessionAPI to receive the sessionId
User one would then call the connect API. The connet api would store this request/defferred result in the hashmap until user 2 joins. Ex
DeferredResult<Task> unconnectedTask = new DeferredResult<Task>();
unconnected.put(sessionId, unconnectedTask);
Now, user one's request would be stored in an in memory map until user two joins
User one would send the sessionId to user two
User two would call the connect API. The connect API would look for the session in the HashMap, and if it exists, it would perform the operations needed, then set the result of the deferred result. Ex
DeferredResult<Task> unconnectedTask = unconnected.get(sessionId);
if(unconnectedTask != null) {
// Do work
unconnectedTask.setResult(task);
} else {
// This is user one's request
}
Please note, this is pseudo code.
put this code both of method,
please import spring transnational jar
#Transactional(propagation =Propagation.REQUIRED,isolation=Isolation.SERIALIZABLE,readOnly=false,transactionManager="transactionManager")
if any issue inform

How to check if button clicked, IF form is actually submitted Selenium / TestNG

I am new to java/selenium/testNG, I have an issue were I run 4 sets of data using the dataprovider, however, One set of data is incorrect just for the purpose of testing that the test works. I first check the button is displayed then clicked. I want to be able to check that the button was clicked and then check if the form was submitted IF the form was not submitted then print error. I am unsure on how to do this my code is below:
WebElement login = driver.findElement(By.id("dijit_form_Button_1_label"));
//If statement - will check if element is Displayed before clicking on login button.
if(login.isDisplayed()){
login.click();
//Main Event is logged If Passed
Reporter.log("Login Form Submitted | ");
logger1.info("Submit Button Clicked");
}else{
Reporter.log("Login Failed | ");
Assert.fail("Login Failed - Check Data | ");
//Main Event Log Fail
}
WebElement logout = driver.findElement(By.id("dijit_form_Button_0_label"));
if(logout.isDisplayed()){
logout.click();
Reporter.log("Logout Successful | ");
}else {
Reporter.log("Logout Failed");
Assert.fail("Logout Failed - Check Data | ");
}
The test displays a error message as "logout Failed" but it should display the first message "Login Failed" How do I get it to check if login and form was submitted successfully?
The reason it prints the second message is the code runs passed that point and selenium cant see the logout button displayed.
Any thoughts on were I am going wrong?
Try this:
private static By outButton = By.id("dijit_form_Button_0_label");
if(driver.findElements(outButton).size() > 0)
{
logout.click();
Reporter.log("Logout Successful | ");
}
after submitting the form, you should make the webdriver wait for some condition to be true.
something like that
int timeout = 30
WebDriverWait wait = new WebDriverWait(driver, timeout);
wait.until(new Function <WebDriver, Boolean>(){
//#Override
public Boolean apply(WebDriver driver) {
//if the login has been successful return true
//if not, return false
}
});

Parse Local Datastore: I can't access ACL secured objects from the network after force closing the app? (Android)

After a successful login I'm calling:
ParseUser currentUser = ParseUser.getCurrentUser();
currentUser.isAuthenticated()
Now if I switch to another app via the home button or multitasking and return to my app the currentUser is still authenticated.
But if I force close the app and then reopen it the currentUser is not authenticated. Therefore it seems that I can't access any objects from the network which have the default Access Control List (ACL) added to them via:
Parse.enableLocalDatastore(this);
ParseACL.setDefaultACL(new ParseACL(), true);
Update with sample code:
// Pinning
ParseObject gameScore = new ParseObject("GameScore");
gameScore.put("score", 1337);
gameScore.put("playerName", "Sean Plott");
gameScore.put("cheatMode", false);
gameScore.pinInBackground("NEW_GAMESCORES", null);
// Syncing Local Changes
ParseQuery<ParseObject> localQueryNewScores = ParseQuery
.getQuery("GameScore");
localQueryNewScores.fromPin("NEW_GAMESCORES");
localQueryNewScores.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scores, ParseException e) {
Log.d("score", "New scores = " + scores.size());
for (ParseObject score : scores) {
score.saveInBackground();
score.unpinInBackground("NEW_GAMESCORES", null);
score.pinInBackground("GAMESCORES", null);
}
}
});
// Syncing Network Changes
ParseQuery<ParseObject> networkQueryScores = ParseQuery
.getQuery("GameScore");
// Query for new results from the network.
networkQueryScores.findInBackground(new FindCallback<ParseObject>() {
public void done(final List<ParseObject> scores, ParseException e) {
Log.d("score", "Network scores = " + scores.size());
// Remove the previously cached results.
ParseObject.unpinAllInBackground("GAMESCORES",
new DeleteCallback() {
public void done(ParseException e) {
// Cache the new results.
ParseObject.pinAllInBackground("GAMESCORES",
scores);
}
});
}
});
// Querying the Local Datastore
ParseQuery<ParseObject> localQueryScores = ParseQuery
.getQuery("GameScore");
localQueryScores.fromPin("GAMESCORES");
localQueryScores.findInBackground(new FindCallback<ParseObject>() {
public void done(List<ParseObject> scores, ParseException e) {
Log.d("score", "Local scores = " + scores.size());
}
});
Log output just after I've ran the code several times:
New scores = 2
Local scores = 0
Network scores = 0
New scores = 0
Local scores = 0
Network scores = 2
New scores = 2
Local scores = 2
Network scores = 2
New scores = 1
Local scores = 2
Network scores = 4
Log output just after I've force closed the app:
New scores = 0
Local scores = 4
Network scores = 0
New scores = 2
Local scores = 0
Network scores = 0
As you can see at Network scores = 0 after the force close I am unable to query any results from the network where I // Query for new results from the network to update the pinned objects in the Local Datastore with new results from the network. This happens even though I am constantly connected to the internet after the first login.
But as I need to sync back changes from the network to the Local Datastore I'm depending on this query.
So how can I still query the network for objects that are stored with ACL added to the currentUser, after I force close the app?
Update 2
I found others with the same problem which has been reported here:
developers.facebook.com/bugs/702967266408226
It seems to be a bug in the new Parse Android SDK 1.5. I will update this post as soon as it's clear that my problem was related to the reported bug.
Maybe save password to file, and if u reopen app after force close, log in with this saved password ?
You could save the username and password in a SharedPreferences and log in again when the user re opens your app.
I think you could just check to see whether getCurrentUser is null or not instead of using isAuthenticated.
boolean isLoggedIn = ParseUser.getCurrentUser() != null;
isAuthenticated states:
Whether the ParseUser has been authenticated on this device. This will
be true if the ParseUser was obtained via a logIn or signUp method.
Only an authenticated ParseUser can be saved (with altered attributes)
and deleted.
getCurrentUser is always the user that has signed up or logged in. So if it is not null, the user is logged in. isAuthenticated is just to see if the user object was retrieved from a login/sign up or not. For example, if you queried for other ParseUser objects, they would not be authenticated.
Also notice that when you do a logOut on the current user, getCurrentUser will be null.
I also noticed that if you were not using the Local Datastore, currentUser.isAuthenticated() would always return true even when force closing the application.
It seems that when you are using the Local Datastore, where the current user is retrieved locally, the object is no longer seen as "authenticated" as in the source is not from a login or sign up.
Parse Android Changelog
v1.5.1 — May 30, 2014
Fixed various bugs with Local Datastore.
The problem was indeed a Local Datastore bug which has been fixed today with the release of the new Parse Android SDK version 1.5.1.

How to accept buddy request properly in Android smack?

There is a openfire server and Android clients (smack). All clients can add each other to buddy/roster list (without authorization, I want user can see each other without accept buddy request). I have some problems of getting the Presence information of the buddy request sender.
Assume there are 2 users - User A, User B.
I can add User B to User A's Roster by:
Roster roster = xmppManager.connection.getRoster();
roster.setSubscriptionMode(Roster.SubscriptionMode.accept_all);
roster.createEntry("userB", "userB#abc.com", null);
I can see User B at User A's roster list. Everything is fine so far
There are few problems with User B. I state what is the problem at the code below:
//I have set the available and status of User A by:
//xmppManager.setStatus(available, bundle.getString("new_status"));
...
// That's how I get Roster and Presence of user A
Roster roster = connection.getRoster();
Collection<RosterEntry> entries = roster.getEntries();
for (RosterEntry entry : entries) {
Presence presence = roster.getPresence(entry.getUser());
// User A always not available even I set User A to available
Log.e(TAG, "presence.isAvailable() = " + presence.isAvailable());
// User A's status always empty
Log.e(TAG, "presence.getStatus() = " + presence.getStatus());
// User A's getName() always null
if (entry.getName() != null)
{
name = entry.getName();
}
else
Log.e(TAG, "GetName is null");
}
Do I need to createEntry() at User A? Or do I need to do something with the buddy request like this?
#Override
public void entriesAdded(Collection<String> collection) {
String user = "";
Iterator<String> it = collection.iterator();
if(it.hasNext()){
user=it.next();
}
Presence presence = new Presence(Presence.Type.subscribe);
presence.setTo(user);
connection.sendPacket(presence);
}
But it does not work. It seems that I need to do something to user B first. Any idea is welcome, thanks!
Okay, I toiled hard at this for a couple of days and finally got things working. I have implemented it with a manual subscription mode (ie. user needs to accept another user's request manually). There is no need to create entries yourself as the server handles this automatically according to the presences sent/received.
For your case (automatic subscription), simply send a subscribe and subscribed presence immediately instead of saving the request locally.
This is how it works:
User1 sends subscribe presence to User2.
Roster entry gets automatically created in User1's roster (but not in User2's roster).
User2 receives subscribe request from User1.
User2 sends back a subscribed presence to User2 (User2 > User1 subscription complete).
User2 checks if User1 is in User2's roster. User1 is not in User2's roster. User2 sends back a subscribe presence to User1.
Roster entry gets automatically created in User2's roster.
User1 receives subscribe presence from User2.
User1 checks if User2 is in User1's roster. User2 is in User1's roster. User1 sends back a subscribed presence to User2 (User2 > User1 subscription complete).
final Presence newPresence = (Presence) packet;
final Presence.Type presenceType = newPresence.getType();
final String fromId = newPresence.getFrom();
final RosterEntry newEntry = getRoster().getEntry(fromId);
if (presenceType == Presence.Type.subscribe)
{
//from new user
if (newEntry == null)
{
//save request locally for later accept/reject
//later accept will send back a subscribe & subscribed presence to user with fromId
//or accept immediately by sending back subscribe and unsubscribed right now
}
//from a user that previously accepted your request
else
{
//send back subscribed presence to user with fromId
}
}

Categories

Resources