Java tutorial
/************************************************************************* * Copyright 2009-2012 Eucalyptus Systems, Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Please contact Eucalyptus Systems, Inc., 6755 Hollister Ave., Goleta * CA 93117, USA or visit http://www.eucalyptus.com/licenses/ if you need * additional information or have any questions. * * This file may incorporate work covered under the following copyright * and permission notice: * * Software License Agreement (BSD License) * * Copyright (c) 2008, Regents of the University of California * All rights reserved. * * Redistribution and use of this software in source and binary forms, * with or without modification, are permitted provided that the * following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. USERS OF THIS SOFTWARE ACKNOWLEDGE * THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE LICENSED MATERIAL, * COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS SOFTWARE, * AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING * IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, * SANTA BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, * WHICH IN THE REGENTS' DISCRETION MAY INCLUDE, WITHOUT LIMITATION, * REPLACEMENT OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO * IDENTIFIED, OR WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT * NEEDED TO COMPLY WITH ANY SUCH LICENSES OR RIGHTS. ************************************************************************/ package com.eucalyptus.auth; import java.security.cert.X509Certificate; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import com.eucalyptus.auth.entities.PolicyEntity; import com.eucalyptus.auth.principal.Policy; import com.eucalyptus.entities.Entities; import org.apache.log4j.Logger; import org.hibernate.FetchMode; import org.hibernate.criterion.Restrictions; import com.eucalyptus.auth.api.AccountProvider; import com.eucalyptus.auth.checker.InvalidValueException; import com.eucalyptus.auth.checker.ValueChecker; import com.eucalyptus.auth.checker.ValueCheckerFactory; import com.eucalyptus.auth.entities.AccessKeyEntity; import com.eucalyptus.auth.entities.AccountEntity; import com.eucalyptus.auth.entities.CertificateEntity; import com.eucalyptus.auth.entities.GroupEntity; import com.eucalyptus.auth.entities.RoleEntity; import com.eucalyptus.auth.entities.UserEntity; import com.eucalyptus.auth.principal.AccessKey; import com.eucalyptus.auth.principal.Account; import com.eucalyptus.auth.principal.Certificate; import com.eucalyptus.auth.principal.Group; import com.eucalyptus.auth.principal.Role; import com.eucalyptus.auth.principal.User; import com.eucalyptus.auth.util.X509CertHelper; import com.eucalyptus.entities.EntityWrapper; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import org.hibernate.persister.collection.CollectionPropertyNames; import javax.persistence.EntityTransaction; /** * The authorization provider based on database storage. This class includes all the APIs to * create/delete/query Eucalyptus authorization entities. */ public class DatabaseAuthProvider implements AccountProvider { private static Logger LOG = Logger.getLogger(DatabaseAuthProvider.class); private static final ValueChecker ACCOUNT_NAME_CHECKER = ValueCheckerFactory.createAccountNameChecker(); public DatabaseAuthProvider() { } @Override @Deprecated public User lookupUserByName(final String userName) throws AuthException { if (userName == null) { throw new AuthException(AuthException.EMPTY_USER_ID); } EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { UserEntity user = DatabaseAuthUtils.getUnique(db, UserEntity.class, "name", userName); db.commit(); return new DatabaseUserProxy(user); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to find user by ID " + userName); throw new AuthException(AuthException.NO_SUCH_USER, e); } } @Override public User lookupUserById(final String userId) throws AuthException { if (userId == null) { throw new AuthException(AuthException.EMPTY_USER_ID); } EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { UserEntity user = DatabaseAuthUtils.getUnique(db, UserEntity.class, "userId", userId); db.commit(); return new DatabaseUserProxy(user); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to find user by ID " + userId); throw new AuthException(AuthException.NO_SUCH_USER, e); } } /** * Lookup enabled user by its access key ID. Only return the user if the key is active. * * @param keyId * @return * @throws AuthException */ @Override public User lookupUserByAccessKeyId(String keyId) throws AuthException { if (keyId == null || "".equals(keyId)) { throw new AuthException("Empty key ID"); } EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { @SuppressWarnings("unchecked") UserEntity result = (UserEntity) db.createCriteria(UserEntity.class).setCacheable(true) .add(Restrictions.eq("enabled", true)).createCriteria("keys").setCacheable(true) .add(Restrictions.and(Restrictions.eq("accessKey", keyId), Restrictions.eq("active", true))) .setReadOnly(true).uniqueResult(); if (result == null) { throw new NoSuchElementException("Can not find user with key " + keyId); } return new DatabaseUserProxy(result); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find user with access key ID : " + keyId); throw new AuthException(AuthException.NO_SUCH_USER, e); } finally { db.rollback(); } } /** * Lookup enabled user by its certificate. Only return the user if the certificate is active and not revoked. * * @param cert * @return * @throws AuthException */ @Override public User lookupUserByCertificate(X509Certificate cert) throws AuthException { if (cert == null) { throw new AuthException("Empty input cert"); } EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { @SuppressWarnings("unchecked") UserEntity result = (UserEntity) db.createCriteria(UserEntity.class).setCacheable(true) .add(Restrictions.eq("enabled", true)).createCriteria("certificates").setCacheable(true) .add(Restrictions.and(Restrictions.eq("pem", X509CertHelper.fromCertificate(cert)), Restrictions.and(Restrictions.eq("active", true), Restrictions.eq("revoked", false)))) .setReadOnly(true).uniqueResult(); if (result == null) { throw new NoSuchElementException("Can not find user with specific cert"); } return new DatabaseUserProxy(result); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find user with certificate : " + cert); throw new AuthException(AuthException.NO_SUCH_USER, e); } finally { db.rollback(); } } @Override public Group lookupGroupById(final String groupId) throws AuthException { if (groupId == null) { throw new AuthException(AuthException.EMPTY_GROUP_ID); } EntityWrapper<GroupEntity> db = EntityWrapper.get(GroupEntity.class); try { GroupEntity group = DatabaseAuthUtils.getUnique(db, GroupEntity.class, "groupId", groupId); db.commit(); return new DatabaseGroupProxy(group); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to find group by ID " + groupId); throw new AuthException(AuthException.NO_SUCH_GROUP, e); } } @Override public List<User> listUsersForAccounts(final Collection<String> accountIds, final boolean eager) throws AuthException { final List<User> results = Lists.newArrayList(); final EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> userAndAccountNumbers = db .createQuery("select u, a.accountNumber from UserEntity u " + "inner join u.groups g " + "inner join g.account a " + "where g.userGroup = true and" + qualifier(accountIds) + " a.accountNumber in (:accountIds)") .setParameterList("accountIds", identifiers(accountIds)).setReadOnly(true).list(); for (final Object[] userAndAccountNumber : userAndAccountNumbers) { final DatabaseUserProxy proxy; if (eager) { Entities.initialize(((UserEntity) userAndAccountNumber[0]).getInfo()); proxy = new DatabaseUserProxy((UserEntity) userAndAccountNumber[0], (String) userAndAccountNumber[1], ((UserEntity) userAndAccountNumber[0]).getInfo()); } else { proxy = new DatabaseUserProxy((UserEntity) userAndAccountNumber[0], (String) userAndAccountNumber[1]); } results.add(proxy); } return results; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get users by account identifiers"); throw new AuthException("Failed to get users by account identifiers", e); } finally { db.rollback(); } } @Override public List<Group> listGroupsForAccounts(final Collection<String> accountIds) throws AuthException { List<Group> results = Lists.newArrayList(); EntityWrapper<GroupEntity> db = EntityWrapper.get(GroupEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> groupAndAccountNumbers = db .createQuery("select g, a.accountNumber from GroupEntity g " + "inner join g.account a " + "where g.userGroup = false and" + qualifier(accountIds) + " a.accountNumber in (:accountIds) ") .setParameterList("accountIds", identifiers(accountIds)).setReadOnly(true).list(); for (final Object[] groupAndAccountNumber : groupAndAccountNumbers) { results.add(new DatabaseGroupProxy((GroupEntity) groupAndAccountNumber[0], (String) groupAndAccountNumber[1])); } return results; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get groups by account identifiers"); throw new AuthException("Failed to get groups by account identifiers", e); } finally { db.rollback(); } } @Override public Map<String, List<Policy>> listPoliciesForUsers(final Collection<String> userIds) throws AuthException { final ArrayListMultimap<String, Policy> results = ArrayListMultimap.create(); final EntityWrapper<PolicyEntity> db = EntityWrapper.get(PolicyEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> policyAndUserIds = db .createQuery("select p, u.userId from PolicyEntity p " + "inner join p.group g " + "inner join g.users u " + "where g.userGroup = true and " + qualifier(userIds) + " u.userId in (:userIds) ") .setParameterList("userIds", identifiers(userIds)).setReadOnly(true).list(); for (final Object[] policyAndUserId : policyAndUserIds) { results.put((String) policyAndUserId[1], new DatabasePolicyProxy((PolicyEntity) policyAndUserId[0])); } return (Map<String, List<Policy>>) (Map) results.asMap(); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get policies by user identifiers"); throw new AuthException("Failed to get policies by user identifiers", e); } finally { db.rollback(); } } @Override public Map<String, List<Policy>> listPoliciesForGroups(final Collection<String> groupIds) throws AuthException { final ArrayListMultimap<String, Policy> results = ArrayListMultimap.create(); final EntityWrapper<PolicyEntity> db = EntityWrapper.get(PolicyEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> policyAndGroupIds = db .createQuery("select p, g.groupId from PolicyEntity p " + "inner join p.group g " + "where g.userGroup = false and " + qualifier(groupIds) + " g.groupId in (:groupIds) ") .setParameterList("groupIds", identifiers(groupIds)).setReadOnly(true).list(); for (final Object[] policyAndGroupId : policyAndGroupIds) { results.put((String) policyAndGroupId[1], new DatabasePolicyProxy((PolicyEntity) policyAndGroupId[0])); } return (Map<String, List<Policy>>) (Map) results.asMap(); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get policies by group identifiers"); throw new AuthException("Failed to get policies by group identifiers", e); } finally { db.rollback(); } } @Override public Map<String, List<Certificate>> listSigningCertificatesForUsers(final Collection<String> userIds) throws AuthException { final ArrayListMultimap<String, Certificate> results = ArrayListMultimap.create(); final EntityWrapper<CertificateEntity> db = EntityWrapper.get(CertificateEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> certificatesAndUserIds = db .createQuery("select c, u.userId from CertificateEntity c " + "inner join c.user u " + "where " + qualifier(userIds) + " u.userId in (:userIds) ") .setParameterList("userIds", identifiers(userIds)).setReadOnly(true).list(); for (final Object[] certificatesAndUserId : certificatesAndUserIds) { results.put((String) certificatesAndUserId[1], new DatabaseCertificateProxy((CertificateEntity) certificatesAndUserId[0])); } return (Map<String, List<Certificate>>) (Map) results.asMap(); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get certificates by user identifiers"); throw new AuthException("Failed to get certificates by user identifiers", e); } finally { db.rollback(); } } @Override public Map<String, List<AccessKey>> listAccessKeysForUsers(final Collection<String> userIds) throws AuthException { final ArrayListMultimap<String, AccessKey> results = ArrayListMultimap.create(); final EntityWrapper<AccessKeyEntity> db = EntityWrapper.get(AccessKeyEntity.class); try { @SuppressWarnings("unchecked") final List<Object[]> keysAndUserIds = db .createQuery("select a, u.userId from AccessKeyEntity a " + "inner join a.user u " + "where " + qualifier(userIds) + " u.userId in (:userIds) ") .setParameterList("userIds", identifiers(userIds)).setReadOnly(true).list(); for (final Object[] keysAndUserId : keysAndUserIds) { results.put((String) keysAndUserId[1], new DatabaseAccessKeyProxy((AccessKeyEntity) keysAndUserId[0])); } return (Map<String, List<AccessKey>>) (Map) results.asMap(); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get access keys by user identifiers"); throw new AuthException("Failed to get access keys by user identifiers", e); } finally { db.rollback(); } } @Override public Role lookupRoleById(final String roleId) throws AuthException { if (roleId == null) { throw new AuthException(AuthException.EMPTY_ROLE_ID); } final EntityWrapper<RoleEntity> db = EntityWrapper.get(RoleEntity.class); try { final RoleEntity role = DatabaseAuthUtils.getUnique(db, RoleEntity.class, "roleId", roleId); return new DatabaseRoleProxy(role); } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find role by ID " + roleId); throw new AuthException(AuthException.NO_SUCH_ROLE, e); } finally { db.rollback(); } } /** * Add account admin user separately. * * @param accountName * @return * @throws AuthException */ @Override public Account addAccount(String accountName) throws AuthException { try { ACCOUNT_NAME_CHECKER.check(accountName); } catch (InvalidValueException e) { Debugging.logError(LOG, e, "Invalid account name " + accountName); throw new AuthException(AuthException.INVALID_NAME, e); } if (DatabaseAuthUtils.checkAccountExists(accountName)) { throw new AuthException(AuthException.ACCOUNT_ALREADY_EXISTS); } AccountEntity account = new AccountEntity(accountName); EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { db.add(account); db.commit(); return new DatabaseAccountProxy(account); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to add account " + accountName); throw new AuthException(AuthException.ACCOUNT_CREATE_FAILURE, e); } } @Override @SuppressWarnings("unchecked") public void deleteAccount(String accountName, boolean forceDeleteSystem, boolean recursive) throws AuthException { if (accountName == null) { throw new AuthException(AuthException.EMPTY_ACCOUNT_NAME); } if (!forceDeleteSystem && DatabaseAuthUtils.isSystemAccount(accountName)) { throw new AuthException(AuthException.DELETE_SYSTEM_ACCOUNT); } if (!recursive && !DatabaseAuthUtils.isAccountEmpty(accountName)) { throw new AuthException(AuthException.ACCOUNT_DELETE_CONFLICT); } EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { if (recursive) { List<GroupEntity> groups = (List<GroupEntity>) db.createCriteria(GroupEntity.class) .setCacheable(true).createCriteria("account").setCacheable(true) .add(Restrictions.eq("name", accountName)).list(); List<UserEntity> users = (List<UserEntity>) db.createCriteria(UserEntity.class).setCacheable(true) .createCriteria("groups").setCacheable(true).add(Restrictions.eq("userGroup", true)) .createCriteria("account").setCacheable(true).add(Restrictions.eq("name", accountName)) .list(); for (GroupEntity g : groups) { db.recast(GroupEntity.class).delete(g); } for (UserEntity u : users) { db.recast(UserEntity.class).delete(u); } } AccountEntity account = (AccountEntity) db.createCriteria(AccountEntity.class).setCacheable(true) .add(Restrictions.eq("name", accountName)).uniqueResult(); if (account == null) { throw new NoSuchElementException("Can not find account " + accountName); } db.delete(account); db.commit(); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to delete account " + accountName); throw new AuthException(AuthException.NO_SUCH_ACCOUNT, e); } } @Override public Set<String> resolveAccountNumbersForName(final String accountNameLike) throws AuthException { final Set<String> results = Sets.newHashSet(); final EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { for (final AccountEntity account : db.query(new AccountEntity(accountNameLike))) { results.add(account.getAccountNumber()); } } catch (Exception e) { Debugging.logError(LOG, e, "Failed to resolve account numbers"); throw new AuthException("Failed to resolve account numbers", e); } finally { db.rollback(); } return results; } @Override public List<User> listAllUsers() throws AuthException { List<User> results = Lists.newArrayList(); EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { List<UserEntity> users = db.query(new UserEntity()); db.commit(); for (UserEntity u : users) { results.add(new DatabaseUserProxy(u)); } return results; } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to get all users"); throw new AuthException("Failed to get all users", e); } } @Override public int countAccounts() throws AuthException { return (int) Entities.count(new AccountEntity()); } @Override public int countUsers() throws AuthException { return (int) Entities.count(new UserEntity()); } @Override public int countGroups() throws AuthException { return (int) Entities.count(new GroupEntity()); } @Override public List<Account> listAllAccounts() throws AuthException { List<Account> results = Lists.newArrayList(); EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { for (AccountEntity account : db.query(new AccountEntity(), true)) { results.add(new DatabaseAccountProxy(account)); } return results; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get accounts"); throw new AuthException("Failed to accounts", e); } finally { db.rollback(); } } @Override public List<Account> listAccountsByStatus(final User.RegistrationStatus status) throws AuthException { List<Account> results = Lists.newArrayList(); EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { @SuppressWarnings("unchecked") final List<AccountEntity> accounts = (List<AccountEntity>) db.createCriteria(AccountEntity.class) .setCacheable(true).createCriteria("groups").setCacheable(true) .add(Restrictions.eq("userGroup", true)).createCriteria("users").setCacheable(true) .add(Restrictions.eq("name", User.ACCOUNT_ADMIN)).add(Restrictions.eq("regStat", status)) .setReadOnly(true).list(); for (AccountEntity a : accounts) { results.add(new DatabaseAccountProxy(a)); } return results; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to get accounts by registration status"); throw new AuthException("Failed to get accounts by registration status", e); } finally { db.rollback(); } } @Override public boolean shareSameAccount(String userId1, String userId2) { if (userId1 == null || userId2 == null) { return false; } if (userId1.equals(userId2)) { return true; } try { User user1 = lookupUserById(userId1); User user2 = lookupUserById(userId2); if (user1.getAccount().getAccountNumber().equals(user2.getAccount().getAccountNumber())) { return true; } } catch (AuthException e) { LOG.warn("User(s) can not be found", e); } return false; } @Override public Certificate lookupCertificate(X509Certificate cert) throws AuthException { if (cert == null) { throw new AuthException("Empty input cert"); } EntityWrapper<CertificateEntity> db = EntityWrapper.get(CertificateEntity.class); try { CertificateEntity certEntity = DatabaseAuthUtils.getUnique(db, CertificateEntity.class, "pem", X509CertHelper.fromCertificate(cert)); db.commit(); return new DatabaseCertificateProxy(certEntity); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to lookup cert " + cert); throw new AuthException(AuthException.NO_SUCH_CERTIFICATE, e); } } @Override public Account lookupAccountByName(String accountName) throws AuthException { if (accountName == null) { throw new AuthException(AuthException.EMPTY_ACCOUNT_NAME); } EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { @SuppressWarnings("unchecked") AccountEntity result = (AccountEntity) db.createCriteria(AccountEntity.class).setCacheable(true) .add(Restrictions.eq("name", accountName)).setReadOnly(true).uniqueResult(); if (result == null) { throw new AuthException(AuthException.NO_SUCH_ACCOUNT); } return new DatabaseAccountProxy(result); } catch (AuthException e) { Debugging.logError(LOG, e, "No matching account " + accountName); throw e; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find account " + accountName); throw new AuthException(AuthException.NO_SUCH_ACCOUNT, e); } finally { db.rollback(); } } @Override public Account lookupAccountById(final String accountId) throws AuthException { if (accountId == null) { throw new AuthException(AuthException.EMPTY_ACCOUNT_ID); } EntityWrapper<AccountEntity> db = EntityWrapper.get(AccountEntity.class); try { AccountEntity account = DatabaseAuthUtils.getUnique(db, AccountEntity.class, "accountNumber", accountId); db.commit(); return new DatabaseAccountProxy(account); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to find account " + accountId); throw new AuthException("Failed to find account", e); } } @Override public Account lookupAccountByCanonicalId(String canonicalId) throws AuthException { if (canonicalId == null || "".equals(canonicalId)) { throw new AuthException(AuthException.EMPTY_CANONICAL_ID); } EntityTransaction tran = Entities.get(AccountEntity.class); try { AccountEntity example = new AccountEntity(); example.setCanonicalId(canonicalId); List<AccountEntity> results = Entities.query(example); if (results != null && results.size() > 0) { AccountEntity found = results.get(0); tran.commit(); return new DatabaseAccountProxy(found); } else { tran.rollback(); LOG.warn("Failed to find account by canonical ID " + canonicalId); throw new AuthException(AuthException.NO_SUCH_USER); } } catch (Exception e) { tran.rollback(); Debugging.logError(LOG, e, "Error occurred looking for account by canonical ID " + canonicalId); throw new AuthException(AuthException.NO_SUCH_USER, e); } } @Override public AccessKey lookupAccessKeyById(final String keyId) throws AuthException { if (keyId == null) { throw new AuthException("Empty access key ID"); } EntityWrapper<AccessKeyEntity> db = EntityWrapper.get(AccessKeyEntity.class); try { AccessKeyEntity keyEntity = DatabaseAuthUtils.getUnique(db, AccessKeyEntity.class, "accessKey", keyId); db.commit(); return new DatabaseAccessKeyProxy(keyEntity); } catch (Exception e) { db.rollback(); Debugging.logError(LOG, e, "Failed to find access key with ID " + keyId); throw new AuthException("Failed to find access key", e); } } @Override public User lookupUserByConfirmationCode(String code) throws AuthException { if (code == null) { throw new AuthException("Empty confirmation code to search"); } EntityWrapper<UserEntity> db = EntityWrapper.get(UserEntity.class); try { @SuppressWarnings("unchecked") UserEntity result = (UserEntity) db.createCriteria(UserEntity.class).setCacheable(true) .add(Restrictions.eq("confirmationCode", code)).setReadOnly(true).uniqueResult(); if (result == null) { throw new AuthException(AuthException.NO_SUCH_USER); } return new DatabaseUserProxy(result); } catch (AuthException e) { Debugging.logError(LOG, e, "Failed to find user by confirmation code " + code); throw e; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find user by confirmation code " + code); throw new AuthException(AuthException.NO_SUCH_USER, e); } finally { db.rollback(); } } public User lookupUserByEmailAddress(String email) throws AuthException { if (email == null || "".equals(email)) { throw new AuthException("Empty email address to search"); } final EntityTransaction tx = Entities.get(UserEntity.class); try { final UserEntity match = (UserEntity) Entities.createCriteria(UserEntity.class).setCacheable(true) .createAlias("info", "i") .add(Restrictions.eq("i." + CollectionPropertyNames.COLLECTION_ELEMENTS, email).ignoreCase()) .setFetchMode("info", FetchMode.JOIN).setReadOnly(true).uniqueResult(); if (match == null) { throw new AuthException(AuthException.NO_SUCH_USER); } boolean emailMatched = false; Map<String, String> info = match.getInfo(); if (info != null) { for (Map.Entry<String, String> entry : info.entrySet()) { if (entry.getKey() != null && User.EMAIL.equals(entry.getKey()) && entry.getValue() != null && email.equalsIgnoreCase(entry.getValue())) { emailMatched = true; break; } } } if (!emailMatched) { throw new AuthException(AuthException.NO_SUCH_USER); } return new DatabaseUserProxy(match); } catch (AuthException e) { Debugging.logError(LOG, e, "Failed to find user by email address " + email); throw e; } catch (Exception e) { Debugging.logError(LOG, e, "Failed to find user by email address " + email); throw new AuthException(AuthException.NO_SUCH_USER, e); } finally { tx.rollback(); } } private String qualifier(final Collection<String> ids) { return ids.isEmpty() ? " not" : ""; } private Collection<String> identifiers(final Collection<String> ids) { return ids.isEmpty() ? Collections.singleton("INVALID") : ids; } }