package org.openslx.bwlp.sat.database.mappers;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.openslx.bwlp.sat.database.Database;
import org.openslx.bwlp.sat.database.MysqlConnection;
import org.openslx.bwlp.sat.database.MysqlStatement;
import org.openslx.bwlp.sat.database.Paginator;
import org.openslx.bwlp.sat.database.models.LocalUser;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.bwlp.thrift.iface.UserInfo;
import org.openslx.util.TimeoutHashMap;
public class DbUser {
private static final Logger LOGGER = Logger.getLogger(DbUser.class);
private static Map<String, UserInfo> userCache;
private static void initCache() throws SQLException {
if (userCache != null)
return;
synchronized (DbUser.class) {
if (userCache == null) {
try (MysqlConnection connection = Database.getConnection()) {
userCache = new TimeoutHashMap<>(TimeUnit.DAYS.toMillis(2));
MysqlStatement stmt = connection.prepareStatement("SELECT userid, firstname, lastname, email, organizationid"
+ " FROM user ORDER BY lastlogin DESC LIMIT 30");
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
UserInfo user = new UserInfo(rs.getString("userid"), rs.getString("firstname"),
rs.getString("lastname"), rs.getString("email"),
rs.getString("organizationid"));
userCache.put(user.userId, user);
}
} catch (SQLException e) {
LOGGER.error("Query failed in DbUser.initCache()", e);
throw e;
}
}
}
}
/**
* Get all users, starting at page <code>page</code>.
* This function will return a maximum of {@link #PER_PAGE} results, so
* you might need to call this method several times.
*
* @param page Page to return. The first page is page 0.
* @return List of {@link UserInfo}
* @throws SQLException
*/
public static List<UserInfo> getAll(int page) throws SQLException {
if (page < 0)
return new ArrayList<>(1);
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("SELECT userid, firstname, lastname, email, organizationid"
+ " FROM user ORDER BY userid ASC " + Paginator.limitStatement(page));
ResultSet rs = stmt.executeQuery();
List<UserInfo> list = new ArrayList<>();
while (rs.next()) {
list.add(new UserInfo(rs.getString("userid"), rs.getString("firstname"),
rs.getString("lastname"), rs.getString("email"), rs.getString("organizationid")));
}
return list;
} catch (SQLException e) {
LOGGER.error("Query failed in DbUser.getAll()", e);
throw e;
}
}
/**
* Get local-only information for given user.
*
* @param user {@link UserInfo} instance representing the user
* @return {@link LocalUser} instance matching the given user, or null if
* not found
* @throws SQLException
*/
public static LocalUser getLocalData(UserInfo user) throws SQLException {
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("SELECT lastlogin, canlogin, issuperuser"
+ " FROM user WHERE userid = :userid LIMIT 1");
stmt.setString("userid", user.userId);
ResultSet rs = stmt.executeQuery();
if (!rs.next())
return null;
return new LocalUser(rs.getLong("lastlogin"), rs.getBoolean("canlogin"),
rs.getBoolean("issuperuser"));
} catch (SQLException e) {
LOGGER.error("Query failed in DbUser.getLocalData()", e);
throw e;
}
}
/**
* Insert given user into db (if not already existent), otherwise just
* update the "lastlogin" field.
*
* @param ui {@link UserInfo}
* @throws SQLException
*/
public static void writeUserOnLogin(UserInfo ui) throws SQLException {
// TODO: Ugly hardcode solution - should be queried from DB, with a nice helper class
if (ui.firstName.length() > 50) {
ui.firstName = ui.firstName.substring(0, 50);
}
if (ui.lastName.length() > 50) {
ui.lastName = ui.lastName.substring(0, 50);
}
if (ui.eMail.length() > 50) {
ui.eMail = ui.eMail.substring(0, 50);
}
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("INSERT INTO user"
+ " (userid, firstname, lastname, email, organizationid, lastlogin, canlogin, issuperuser)"
+ " VALUES"
+ " (:userid, :firstname, :lastname, :email, :organizationid, UNIX_TIMESTAMP(), 1, 0)"
+ " ON DUPLICATE KEY UPDATE lastlogin = UNIX_TIMESTAMP(), email = VALUES(email),"
+ " firstname = VALUES(firstname), lastname = VALUES(lastname)");
stmt.setString("userid", ui.userId);
stmt.setString("firstname", ui.firstName);
stmt.setString("lastname", ui.lastName);
stmt.setString("email", ui.eMail);
stmt.setString("organizationid", ui.organizationId);
stmt.executeUpdate();
connection.commit();
} catch (SQLException e) {
LOGGER.error("Query failed in DbUser.writeUserOnLogin()", e);
throw e;
}
synchronized (DbUser.class) {
initCache();
userCache.put(ui.userId, ui);
}
}
public static UserInfo getCached(String userId) throws SQLException, TNotFoundException {
synchronized (DbUser.class) {
initCache();
UserInfo user = userCache.get(userId);
if (user != null)
return user;
}
try (MysqlConnection connection = Database.getConnection()) {
MysqlStatement stmt = connection.prepareStatement("SELECT userid, firstname, lastname, email, organizationid"
+ " FROM user WHERE userid = :userid");
stmt.setString("userid", userId);
ResultSet rs = stmt.executeQuery();
if (!rs.next())
throw new TNotFoundException();
UserInfo user = new UserInfo(rs.getString("userid"), rs.getString("firstname"),
rs.getString("lastname"), rs.getString("email"), rs.getString("organizationid"));
synchronized (DbUser.class) {
userCache.put(user.userId, user);
}
return user;
} catch (SQLException e) {
LOGGER.error("Query failed in DbUser.getCached()", e);
throw e;
}
}
}