BulkAccounts.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.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import net.metanotion.authident.AuthPassword;
import net.metanotion.authident.Realm;
import net.metanotion.authident.UserToken;
import net.metanotion.functor.Block;
import net.metanotion.util.JDBCTransaction;
/** This is a utility class to enable components to create accounts "in bulk" and do so without having to specify
passwords, instead an email is sent with a password reset link. */
public final class BulkAccounts {
private static final Queries DB = new Queries();
private final DataSource ds;
private final AuthStore store;
private final Realm r;
private final AuthPassword pw;
private final AuthMailer mailer;
/** Create an instance of a bulk account creation utility for a specific realm.
@param ds A data source for the SQL database that provides persistance for the extended information about accounts(see
src/main/sql/auth.schema.sql for the DDL).
@param r An instance of the realm to create identities to associate with the usernames.
@param pw An instance of a password authentication service from the net.metanotion.authident package. This is used to
create accounts.
@param mailer An instance of mailing service to send transactional emails related to account actions(e.g. account
validation, password resets, and so on). A null implementation that simply logs API calls is provided by
DefaultAuthMailer.
*/
public BulkAccounts(final DataSource ds, final Realm r, final AuthPassword pw, final AuthMailer mailer) {
this.ds = ds;
this.store = new AuthStoreJDBC(ds);
this.r = r;
this.pw = pw;
this.mailer = mailer;
}
/** Create accounts for all the users in the list and send them welcome emails.
@param emails The list of emails to create accounts and send emails for.
@return A list of accounts that couldn't be created.
*/
public List<String> addAccounts(final Iterable<String> emails) {
final ArrayList<String> failures = new ArrayList<>();
for(final String email: emails) {
final UserToken ut = r.createUser();
try {
this.pw.addAuthentication(ut, email);
final ResetCode rc = store.createReset(email);
mailer.welcomeWithPasswordReset(email, Integer.toString(rc.ResetID), URLEncoder.encode(rc.UUID, "UTF-8"));
} catch (final UnsupportedEncodingException uee) {
throw new AssertionError("UTF-8 is always supported", uee);
} catch (final RuntimeException re) {
failures.add(email);
ut.delete();
}
}
return failures;
}
/** Update the roles for a user account.
@param uid The user account to update.
@param roleList The list of roles to associate with the user account.
*/
public void updateRoles(final UserToken uid, final Iterable<String> roleList) {
JDBCTransaction.doTX(ds, new Block<Connection,Boolean>() {
@Override public Boolean eval(final Connection conn) throws Exception {
DB.deleteRoles(conn, uid.getID());
for(final String role: roleList) {
DB.addRole(conn, uid.getID(), role);
}
return true;
}
});
}
}