package net.thesocialos.server;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Random;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpSession;
import net.thesocialos.client.service.UserService;
import net.thesocialos.server.utils.BCrypt;
import net.thesocialos.shared.LoginResult;
import net.thesocialos.shared.ChannelApiEvents.ChApiChatUserChngState.STATETYPE;
import net.thesocialos.shared.ChannelApiEvents.ChApiContactNew;
import net.thesocialos.shared.exceptions.UserExistsException;
import net.thesocialos.shared.exceptions.UserUpdateException;
import net.thesocialos.shared.exceptions.UsersNotFoundException;
import net.thesocialos.shared.model.Account;
import net.thesocialos.shared.model.Columns;
import net.thesocialos.shared.model.Google;
import net.thesocialos.shared.model.ImageUpload;
import net.thesocialos.shared.model.Session;
import net.thesocialos.shared.model.User;
import com.google.appengine.api.channel.ChannelFailureException;
import com.google.gwt.user.server.rpc.XsrfProtectedServiceServlet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyOpts;
import com.googlecode.objectify.ObjectifyService;
@SuppressWarnings("serial")
public class UserServiceImpl extends XsrfProtectedServiceServlet implements UserService {
@Override
public String getChannel() {
try {
Objectify ofy = ObjectifyService.begin();
User user = UserHelper.getUserSession(perThreadRequest.get().getSession(), ofy);
user.setTokenChannel(ChannelApiHelper.createChannel(perThreadRequest.get().getSession()));
ofy.put(user);
return user.getTokenChannel();
} catch (ChannelFailureException e) {
e.printStackTrace();
}
return null;
}
@Override
public void destroy() {
}
@Override
public Map<Key<Account>, Account> getCloudAccounts() {
Objectify ofy = ObjectifyService.begin();
removeDeletedAccounts(ofy);
User user = UserHelper
.getUserWithEmail(UserHelper.getUserHttpSession(perThreadRequest.get().getSession()), ofy);
List<Key<? extends Account>> accountsKeys = user.getAccounts();
Map<Key<Account>, Account> accounts = ofy.get(accountsKeys);
if (refreshAccountTokens(accounts, ofy)) return ofy.get(accountsKeys);
return accounts;
}
@Override
public Map<Key<Columns>, Columns> getDeckColumns() {
Objectify ofy = ObjectifyService.begin();
removeDeletedColumns(ofy);
User user = UserHelper
.getUserWithEmail(UserHelper.getUserHttpSession(perThreadRequest.get().getSession()), ofy);
List<Key<Columns>> columns = user.getColumns();
if (null == columns || columns.isEmpty()) populateDefaultColumns(ofy, user);
else if (user.getEmail().equalsIgnoreCase("endika2@gmail.com")) {
Map<Key<Columns>, Columns> columnas = ofy.get(columns);
Iterator<Columns> it = columnas.values().iterator();
boolean metrobilbao = false;
while (it.hasNext()) {
Columns c = it.next();
if (c.getType() == Columns.TYPE.SEARCH && c.getValue().equalsIgnoreCase("metrobilbao")) {
metrobilbao = true;
break;
}
}
if (!metrobilbao) {
user.addColumn(ofy.put(new Columns(Columns.TYPE.SEARCH, "metrobilbao")));
ofy.put(user);
}
}
return ofy.get(user.getColumns());
}
@Override
public User getLoggedUser(String sid) {
ObjectifyOpts opts = new ObjectifyOpts().setSessionCache(true);
Objectify ofy = ObjectifyService.begin(opts);
User user;
Session session;
HttpSession httpSession = perThreadRequest.get().getSession();
if ((session = UserHelper.getSesssionHttpSession(httpSession)) != null
&& (user = UserHelper.getUserWithEmail(UserHelper.getUserHttpSession(httpSession), ofy)) != null)
if (session.getSessionID().equalsIgnoreCase(sid)
&& session.getUser().getName().equalsIgnoreCase(user.getEmail()))
// return User.toDTO(user);
User.toDTO(user.getEmail(), user.getUrlAvatar(), user.getBackground(), user.getName(),
user.getLastName(), user.getRole(), user.getMobilePhone(), user.getAddress(), user.getBio(),
user.getTokenChannel());
try {
session = UserHelper.getSessionWithCookies(sid, ofy);
user = UserHelper.getUserWithSession(session, ofy);
user.setLastTimeActive(new Date());
UserHelper.saveUsertohttpSession(session, user.getEmail(), httpSession);
ofy.put(user);
UserHelper.checkChannelIsConnected(httpSession, ofy);
// return User.toDTO(user);
return User.toDTO(user.getEmail(), user.getUrlAvatar(), user.getBackground(), user.getName(),
user.getLastName(), user.getRole(), user.getMobilePhone(), user.getAddress(), user.getBio(),
user.getTokenChannel());
} catch (NotFoundException e) {
e.printStackTrace();
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public LoginResult login(String email, String password, boolean keeploged) {
// Duration remembering login. 30 days in this case.
long duration = 2592000000L;// 1000l * 60l * 60l * 24l * 30l;
Objectify ofy = ObjectifyService.begin();
User user;
HttpSession httpSession = perThreadRequest.get().getSession();
try {
user = UserHelper.getUserWithEmail(email, ofy);
} catch (NotFoundException e) {
return null;
}
if (!BCrypt.checkpw(password, user.getPassword())) return null;
Key<User> userKey = ObjectifyService.factory().getKey(user);
Session session = new Session(httpSession.getId(), new Date(System.currentTimeMillis() + duration), userKey);
if (keeploged)
// Add new session to user
UserHelper.addSessiontoUser(user, session, duration, ofy);
else
duration = -1;
user.setLastTimeActive(new Date()); // Set last time to user is login
// Store user and session
UserHelper.saveUsertohttpSession(session, user.getEmail(), httpSession);
ofy.put(user); // Save user
UserHelper.checkChannelIsConnected(httpSession, ofy);
// return new LoginResult(User.toDTO(user), httpSession.getId(), duration);
return new LoginResult(User.toDTO(user.getEmail(), user.getUrlAvatar(), user.getBackground(), user.getName(),
user.getLastName(), user.getRole(), user.getMobilePhone(), user.getAddress(), user.getBio(),
user.getTokenChannel()), httpSession.getId(), duration);
}
@Override
public void logout() {
getThreadLocalRequest().getSession().invalidate();
return;
}
private void populateDefaultColumns(Objectify ofy, User user) {
user.setColumns(new ArrayList<Key<Columns>>());
user.addColumn(ofy.put(new Columns(Columns.TYPE.TIMELINE, Columns.HOME)));
user.addColumn(ofy.put(new Columns(Columns.TYPE.TIMELINE, Columns.USER)));
if (user.getEmail().equalsIgnoreCase("endika2@gmail.com"))
user.addColumn(ofy.put(new Columns(Columns.TYPE.SEARCH, "metrobilbao")));
ofy.put(user);
}
private boolean refreshAccountTokens(Map<Key<Account>, Account> accounts, Objectify ofy) {
boolean changed = false;
Iterator<Account> it = accounts.values().iterator();
while (it.hasNext()) {
Account ac = it.next();
if (ac instanceof Google) {
Google gac = (Google) ac;
if (null == gac.getExpireDate() || gac.getExpireDate().before(new Date())) {
changed = true;
ofy.put(RefreshTokens.refreshGoogle(gac));
}
}
}
return changed;
}
@Override
public void register(User user) throws UserExistsException {
Objectify ofy = ObjectifyService.begin();
try {
ofy.get(User.class, user.getEmail());
throw new UserExistsException("Email '" + user.getEmail() + "' already registered");
} catch (NotFoundException e) {
user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
ofy.put(user); // Save
}
// user = new User(email, BCrypt.hashpw(password, BCrypt.gensalt()),
// name, lastName); // Encrypt the password
}
private void removeDeletedAccounts(Objectify ofy) {
HttpSession httpSession = perThreadRequest.get().getSession();
User user = UserHelper.getUserWithEmail(UserHelper.getUserHttpSession(httpSession), ofy);
List<Key<? extends Account>> accountsKeys = user.getAccounts();
List<Key<? extends Account>> newAccountsKeys = new ArrayList<Key<? extends Account>>();
Iterator<Key<? extends Account>> it = accountsKeys.iterator();
while (it.hasNext()) {
Key<? extends Account> accountKey = it.next();
try {
Account ac = ofy.get(accountKey);
if (null != ac) newAccountsKeys.add(accountKey);
} catch (NotFoundException ex) {
ex.printStackTrace();
System.out.println("Key not found proceeding to remove it from the user object");
}
}
user.overwriteAccountsList(newAccountsKeys);
ofy.put(user);
}
private void removeDeletedColumns(Objectify ofy) {
HttpSession httpSession = perThreadRequest.get().getSession();
User user = UserHelper.getUserWithEmail(UserHelper.getUserHttpSession(httpSession), ofy);
List<Key<Columns>> columnsKeys = user.getColumns();
List<Key<Columns>> newColumnsKeys = new ArrayList<Key<Columns>>();
Iterator<Key<Columns>> it = columnsKeys.iterator();
while (it.hasNext()) {
Key<Columns> columnKey = it.next();
try {
Columns col = ofy.get(columnKey);
if (null != col) newColumnsKeys.add(columnKey);
} catch (NotFoundException ex) {
ex.printStackTrace();
System.out.println("Key not found proceeding to remove it from the user object");
}
}
user.overwriteColumnsList(newColumnsKeys);
ofy.put(user);
}
private void removeUserColumns(User user) {
Objectify ofy = ObjectifyService.begin();
ofy.delete(user.getColumns());
}
@Override
public void setDeckColumns(ArrayList<Columns> columns) {
Objectify ofy = ObjectifyService.begin();
User user = UserHelper
.getUserWithEmail(UserHelper.getUserHttpSession(perThreadRequest.get().getSession()), ofy);
Map<Key<Columns>, Columns> mColumns = ofy.put(columns);
removeUserColumns(user);
user.setColumns(new ArrayList<Key<Columns>>(mColumns.keySet()));
}
@Override
public void addDeckColumn(Columns column) {
Objectify ofy = ObjectifyService.begin();
User user = UserHelper
.getUserWithEmail(UserHelper.getUserHttpSession(perThreadRequest.get().getSession()), ofy);
user.addColumn(ofy.put(column));
ofy.put(user);
}
@Override
public void checkChannel(ChApiContactNew newContact) {
/*
* ChannelApiHelper.sendMessage("unai@thesocialos.net", ChannelApiHelper.encodeMessage(new
* ChApiContactNew("perico@gmail.com"))); ChannelApiHelper.sendMessage("unai@thesocialos.net",
* ChannelApiHelper.encodeMessage(new ChApiChatRecvMessage(null, "palomo@gmail.com", "hola")));
* ChannelApiHelper.sendMessage("unai@thesocialos.net", ChannelApiHelper.encodeMessage(new
* ChApiChatUserChngState(STATETYPE.ONLINE, null, "palomo@gmail.com")));
* ChannelApiHelper.sendMessage("unai@thesocialos.net", ChannelApiHelper.encodeMessage(new
* ChApiChatUserConnected("palomo@gmail.com"))); ChannelApiHelper.sendMessage("unai@thesocialos.net",
* ChannelApiHelper.encodeMessage(new ChApiChatUserDisconnect("palomo@gmail.com")));
* ChannelApiHelper.sendMessage("unai@thesocialos.net", ChannelApiHelper.encodeMessage(new
* ChApiPetitionNew("lolita5@hotmail.com")));
*/
}
@Override
public void setState(STATETYPE statetype, String customMsg) {
Objectify ofy = ObjectifyService.begin();
User user = ofy.get(User.class, UserHelper.getUserHttpSession(perThreadRequest.get().getSession()));
user.chatState = statetype;
ofy.put(user);
ChannelApiHelper.sendStateToContacts(ofy.get(user.getContacts()).values().iterator(), statetype, customMsg,
Key.create(User.class, user.getEmail()));
}
@Override
public User updateUser(User user) throws UserUpdateException {
Objectify ofy = ObjectifyService.begin();
if (UserHelper.getUserHttpSession(perThreadRequest.get().getSession()).equalsIgnoreCase(user.getEmail())) {
User ofyUser = ofy.get(User.class, UserHelper.getUserHttpSession(perThreadRequest.get().getSession()));
ofyUser.setBio(user.getBio());
ofyUser.setAddress(user.getAddress());
ofyUser.setFirstName(user.getFirstName());
ofyUser.setLastName(user.getLastName());
ofyUser.setMobilePhone(user.getMobilePhone());
ofy.put(ofyUser);
return User.toDTO(ofyUser.getEmail(), ofyUser.getUrlAvatar(), ofyUser.getBackground(), ofyUser.getName(),
ofyUser.getLastName(), ofyUser.getRole(), ofyUser.getMobilePhone(), ofyUser.getAddress(),
ofyUser.getBio(), ofyUser.getTokenChannel());
}
throw new UserUpdateException("UserEmail not equals");
}
@Override
public String getAvatar() {
Objectify ofy = ObjectifyService.begin();
ImageUpload avatar;
User user = UserHelper
.getUserWithEmail(UserHelper.getUserHttpSession(perThreadRequest.get().getSession()), ofy);
return user.getUrlAvatar();
}
@Override
public void deleteCloudAccount(Account account) {
Objectify ofy = ObjectifyService.begin();
Key<Account> accountKey = Key.create(Account.class, account.getId());
User user = ofy.get(User.class, UserHelper.getUserHttpSession(perThreadRequest.get().getSession()));
user.deleteAccount(accountKey);
ofy.delete(accountKey);
ofy.put(user);
}
@Override
public void sendResetPass(String email) throws UsersNotFoundException {
Objectify ofy = ObjectifyService.begin();
User user;
try {
user = ofy.get(User.class, email);
} catch (NotFoundException e) {
throw new UsersNotFoundException("User not exist");
}
Properties props = new Properties();
javax.mail.Session session = javax.mail.Session.getDefaultInstance(props, null);
try {
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("unai@thesocialos.net", "SocialOS Administrator"));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress("email", "Mr. User"));
Random random = new Random();
Integer password = (int) (random.nextFloat() * 1000000);
msg.setSubject("Your reset password");
String sendText = new String();
sendText = "<img src='http://www.thesocialos.net/images/logo-big.png'/><table border='1'><tr><td>User:</td>"
+ "<td>"
+ email
+ "</td></tr><tr><td>Password:</td>"
+ "<td>"
+ password
+ "</td>"
+ "</tr>"
+ "</table>";
msg.setContent(sendText, "text/html");
Transport.send(msg);
user.setPassword(BCrypt.hashpw(String.valueOf(password), BCrypt.gensalt()));
ofy.put(user);
} catch (AddressException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
@Override
public Boolean changePassWord(String oldPassWord, String newPassword) {
Objectify ofy = ObjectifyService.begin();
User user;
try {
user = UserHelper.getUserSession(perThreadRequest.get().getSession(), ofy);
} catch (NotFoundException e) {
return false;
}
if (!BCrypt.checkpw(oldPassWord, user.getPassword())) return false;
user.setPassword(BCrypt.hashpw(newPassword, BCrypt.gensalt()));
ofy.put(user);
return true;
}
}