AuthStoreJDBC.java
/***************************************************************************
Copyright 2014 Emily Estes
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***************************************************************************/
package net.metanotion.formsauth;
import java.security.SecureRandom;
import java.sql.Connection;
import java.util.List;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.metanotion.authident.UserToken;
import net.metanotion.functor.Block;
import net.metanotion.util.Base64;
import net.metanotion.util.JDBCTransaction;
final class AuthStoreJDBC implements AuthStore {
private static final Logger logger = LoggerFactory.getLogger(AuthStoreJDBC.class);
private static final Queries q = new Queries();
private static final int SECRET_TOKEN_LENGTH = 48;
private static final SecureRandom random = new SecureRandom();
private static String randomBase64String(final int byteLength) {
final byte[] string = new byte[byteLength];
random.nextBytes(string);
return Base64.encode(string);
}
private final DataSource ds;
public AuthStoreJDBC(final DataSource ds) { this.ds = ds; }
@Override public ValidationCode createValidation(final String username) {
return JDBCTransaction.doTX(ds, new Block<Connection, ValidationCode>() {
@Override public ValidationCode eval(final Connection conn) throws Exception {
logger.debug("Looking up validation code for {}", username);
for(final ValidationCode vc: q.getValidationCode(conn, username)) { return vc; }
logger.debug("not found, so generate one.");
final ValidationCode vc = new ValidationCode();
vc.ValidateID = q.reserveVID(conn);
vc.UUID = AuthStoreJDBC.randomBase64String(SECRET_TOKEN_LENGTH);
logger.debug("attempting to add validation code");
q.addValidationCode(conn, username, vc.ValidateID, vc.UUID);
return vc;
};
});
}
@Override public ResetCode createReset(final String username) {
return JDBCTransaction.doTX(ds, new Block<Connection, ResetCode>() {
@Override public ResetCode eval(final Connection conn) throws Exception {
logger.debug("Looking up reset code for {}", username);
for(final ResetCode rc: q.getResetCode(conn, username)) { return rc; }
logger.debug("Not found, generating one.");
final ResetCode rc = new ResetCode();
rc.ResetID = q.reserveRID(conn);
rc.UUID = AuthStoreJDBC.randomBase64String(SECRET_TOKEN_LENGTH);
logger.debug("attempting to add reset code");
q.addResetCode(conn, username, rc.ResetID, rc.UUID);
return rc;
};
});
}
@Override public String lookupUsernameForResetCode(final long rid, final String token) throws Exception {
try (final Connection conn = ds.getConnection()) {
for(final String u: q.getResetCodeByToken(conn, rid, token)) { return u; }
return null;
}
}
@Override public void clearResetCode(final String username) throws Exception {
try (final Connection conn = ds.getConnection()) {
q.deleteResetCode(conn, username);
}
}
@Override public String lookupUsernameForValidationCode(final long vid, final String token) throws Exception {
try (final Connection conn = ds.getConnection()) {
for(final String u: q.getValidationCodeByToken(conn, vid, token)) { return u; }
return null;
}
}
@Override public void validateUser(final String username) {
// delete the token.
JDBCTransaction.doTX(ds, new Block<Connection, Integer>() {
@Override public Integer eval(final Connection conn) throws Exception {
q.validateUsername(conn, username);
return q.deleteValidationCode(conn, username);
}
});
}
@Override public List<Account> listAccounts(final UserToken ut) throws Exception {
try (final Connection conn = ds.getConnection()) {
return q.getAccounts(conn, ut.getID());
}
}
}