/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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 org.apereo.portal.tenants;
import java.util.Collections;
import java.util.Set;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest;
import org.apereo.portal.IUserIdentityStore;
import org.apereo.portal.persondir.ILocalAccountDao;
import org.apereo.portal.persondir.ILocalAccountPerson;
import org.apereo.portal.portlets.account.IPasswordResetNotification;
import org.apereo.portal.portlets.account.UserAccountHelper;
import org.apereo.portal.url.IPortalRequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Integrates with the 'forgot-password' framework portlet to grant the tenant admin contact access
* via local authentication when a new tenant is created.
*
* <p>This behavior is completely optional. You can add or remove it by adjusting the
* 'tenantOperationsListeners' bean in servicesContext.xml.
*
* @since 4.1
*/
public final class ResetPasswordTenantOperationsListener extends AbstractTenantOperationsListener {
public static final String ADMIN_CONTACT_USERNAME = "adminContactUsername";
public static final String ADMIN_CONTACT_EMAIL = "adminContactEmail";
private static final String TENANT_ADMIN_EMAIL_SENT = "tenant.admin.email.sent";
private static final String UNABLE_TO_SEND_TENANT_ADMIN_EMAIL =
"unable.to.send.tenant.admin.email";
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired private IUserIdentityStore userIdentityStore;
@Autowired private ILocalAccountDao localAccountDao;
@Autowired private IPortalRequestUtils portalRequestUtils;
@Autowired private UserAccountHelper userAccountHelper;
private IPasswordResetNotification passwordResetNotification;
public ResetPasswordTenantOperationsListener() {
super("reset-password");
}
@Autowired
public void setPasswordResetNotification(IPasswordResetNotification passwordResetNotification) {
this.passwordResetNotification = passwordResetNotification;
}
/** This step is not required */
@Override
public boolean isOptional() {
return true;
}
@Override
public TenantOperationResponse onCreate(final ITenant tenant) {
return prepareResponse(tenant);
}
@Override
public TenantOperationResponse onUpdate(final ITenant tenant) {
// Send the same email here as well, in case the contact changes
return prepareResponse(tenant);
}
/** @since 4.3 */
@Override
public Set<ITenantManagementAction> getAvaialableActions() {
ITenantManagementAction rslt =
new ITenantManagementAction() {
@Override
public String getFname() {
return "resend-admin-email";
}
@Override
public String getMessageCode() {
return "resend.admin.email";
}
@Override
public TenantOperationResponse invoke(final ITenant tenant) {
return prepareResponse(tenant);
}
};
return Collections.singleton(rslt);
}
@Override
public void validateAttribute(final String key, final String value) throws Exception {
switch (key) {
case ADMIN_CONTACT_USERNAME:
if (!userIdentityStore.validateUsername(value)) {
throw new IllegalArgumentException("Invalid username: " + value);
}
break;
case ADMIN_CONTACT_EMAIL:
InternetAddress emailAddr = new InternetAddress(value);
emailAddr.validate();
break;
default:
// No problem; fall through
}
}
/*
* Implementation
*/
private TenantOperationResponse prepareResponse(final ITenant tenant) {
try {
sendResetPasswordEmail(tenant);
} catch (Exception e) {
log.error(
"Failed to send tenant admin email to address {} for tenant {}",
tenant.getAttribute(ADMIN_CONTACT_EMAIL),
tenant.getName(),
e);
final TenantOperationResponse error =
new TenantOperationResponse(
this, TenantOperationResponse.Result.FAIL); // Just a warning
error.addMessage(
createLocalizedMessage(
UNABLE_TO_SEND_TENANT_ADMIN_EMAIL,
new String[] {tenant.getAttribute(ADMIN_CONTACT_EMAIL)}));
return error;
}
final TenantOperationResponse rslt =
new TenantOperationResponse(this, TenantOperationResponse.Result.SUCCESS);
rslt.addMessage(
createLocalizedMessage(
TENANT_ADMIN_EMAIL_SENT,
new String[] {tenant.getAttribute(ADMIN_CONTACT_EMAIL)}));
return rslt;
}
private void sendResetPasswordEmail(final ITenant tenant) {
ILocalAccountPerson admin =
localAccountDao.getPerson(tenant.getAttribute(ADMIN_CONTACT_USERNAME));
admin.setAttribute("loginToken", userAccountHelper.getRandomToken());
final HttpServletRequest http = portalRequestUtils.getCurrentPortalRequest();
this.userAccountHelper.sendLoginToken(http, admin, passwordResetNotification);
localAccountDao.updateAccount(admin);
}
}