/*
* Copyright (c) 2005-2010, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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
*
* 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 org.wso2.carbon.tenant.mgt.services;
import org.apache.axis2.AxisFault;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.multitenancy.persistence.TenantPersistor;
import org.wso2.carbon.registry.core.RegistryConstants;
import org.wso2.carbon.registry.core.Resource;
import org.wso2.carbon.registry.core.exceptions.RegistryException;
import org.wso2.carbon.registry.core.session.UserRegistry;
import org.wso2.carbon.tenant.mgt.util.TenantMgtUtil;
import org.wso2.carbon.user.core.UserStoreException;
import org.wso2.carbon.user.core.tenant.Tenant;
import org.wso2.carbon.user.core.tenant.TenantManager;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import org.wso2.carbon.common.constants.StratosConstants;
import org.wso2.carbon.common.util.CommonUtil;
import org.wso2.carbon.tenant.mgt.beans.CaptchaInfoBean;
import org.wso2.carbon.tenant.mgt.beans.TenantInfoBean;
import org.wso2.carbon.tenant.mgt.internal.TenantMgtServiceComponent;
import org.wso2.carbon.tenant.mgt.internal.util.CaptchaUtil;
import org.wso2.carbon.tenant.mgt.internal.util.PasswordUtil;
/**
* TenantSelfRegistration - This is the Web service that will be called when
* tenants register themselves
*/
public class TenantSelfRegistrationService {
private static final Log log = LogFactory.getLog(TenantSelfRegistrationService.class);
/**
* Registers a tenant - Tenant Self Registration
*
* @param tenantInfoBean - tenantInformation
* @param captchaInfoBean - captchaInformation
* @return String UUID
* @throws Exception if the tenant registration fails.
*/
public String registerTenant(TenantInfoBean tenantInfoBean, CaptchaInfoBean captchaInfoBean)
throws Exception {
// validate the email
try {
CommonUtil.validateEmail(tenantInfoBean.getEmail());
} catch (Exception e) {
String msg = "Invalid email is provided.";
log.error(msg, e);
throw new AxisFault(msg);
}
// validate the domain
String domainName = tenantInfoBean.getTenantDomain();
try {
TenantMgtUtil.validateDomain(domainName);
} catch (Exception e) {
String msg = "Domain Validation Failed.";
log.error(msg, e);
throw new AxisFault(msg);
}
// validate the first/last names
String firstname = tenantInfoBean.getFirstname();
String lastname = tenantInfoBean.getLastname();
try {
CommonUtil.validateName(firstname, "First Name");
CommonUtil.validateName(lastname, "Last Name");
} catch (Exception e) {
String msg = "First/Last Name Validation Failed.";
log.error(msg, e);
throw new AxisFault(msg);
} // now validate the captcha
try {
CaptchaUtil.validateCaptcha(captchaInfoBean);
if (log.isDebugEnabled()) {
log.debug("Captcha Successfully Validated.");
}
} catch (Exception e) {
String msg = StratosConstants.CAPTCHA_ERROR_MSG;
log.error(msg, e);
throw new AxisFault(msg);
} finally {
try {
CaptchaUtil.cleanCaptcha(captchaInfoBean.getSecretKey());
} catch (Exception e) {
String msg = "Error in cleaning captcha. ";
log.error(msg, e);
// not throwing the exception in finally more up.
}
}
// persists the tenant.
Tenant tenant = TenantMgtUtil.initializeTenant(tenantInfoBean);
TenantPersistor persistor = TenantMgtServiceComponent.getTenantPersistor();
persistor.persistTenant(tenant, true, tenantInfoBean.getSuccessKey(), tenantInfoBean.getOriginatedService());
TenantMgtUtil.addClaimsToUserStoreManager(tenant);
// For the registration validation - mail for the tenant email address
TenantMgtUtil.sendEmail(tenant, tenantInfoBean.getOriginatedService());
// Notifies the super admin about the new tenant creation
TenantMgtUtil.notifyTenantCreationToSuperAdmin(
tenantInfoBean.getTenantDomain(), tenantInfoBean.getAdmin(),
tenantInfoBean.getEmail());
//adding the subscription entry
try{
boolean subscriptionAdded = TenantMgtUtil.addUsagePlan(tenantInfoBean);
if(subscriptionAdded){
log.debug("Subscription added successfully for the tenant: " + tenantInfoBean.getTenantDomain());
}else{
log.error("Could not add the subscription for tenant: " + tenantInfoBean.getTenantDomain());
}
}catch(Exception e){
log.error("Error occurred while adding the subscription for tenant: " +
tenantInfoBean.getTenantDomain() + " " + e.getMessage(), e);
}
return TenantMgtUtil.prepareStringToShowThemeMgtPage(tenant.getId());
}
/**
* Handling the User Request for a password reset
*
* @param tenantInfoBean tenant info bean
* @return true if successful
* @throws Exception, if exception occurred in validating the domain.
*/
public boolean resetPassword(TenantInfoBean tenantInfoBean) throws Exception {
// validate the domain
try {
TenantMgtUtil.validateDomain(tenantInfoBean.getTenantDomain());
} catch (Exception e) {
String msg = "Domain Validation Failed.";
log.error(msg, e);
// Password Reset Failed. Not passing the error details to client.
return false;
}
return PasswordUtil.resetPassword(tenantInfoBean);
}
/**
* Update the password with the new password provided by the user
*
* @param tenantInfoBean tenantInfo
* @param captchaInfoBean captcha
* @return true if password is changed successfully. Final call in password
* reset.
* @throws Exception, if captcha validation failed.
*/
public boolean updateAdminPasswordWithUserInput(
TenantInfoBean tenantInfoBean, CaptchaInfoBean captchaInfoBean) throws Exception {
// Validate the captcha
try {
CaptchaUtil.validateCaptcha(captchaInfoBean);
} catch (Exception e) {
String msg = StratosConstants.CAPTCHA_ERROR_MSG;
log.error(msg, e);
throw new AxisFault(msg);
} finally {
try {
CaptchaUtil.cleanCaptcha(captchaInfoBean.getSecretKey());
} catch (Exception e) {
String msg = "Error in cleaning captcha. ";
log.error(msg, e);
// not throwing the exception in finally more up.
}
}
// change the password with the user input password
TenantMgtAdminService tenantMgtAdminService = new TenantMgtAdminService();
if (log.isDebugEnabled()) {
log.debug("Initializing TenantMgtAdminService for the admin account configuration.");
}
return tenantMgtAdminService.updateTenantPassword(tenantInfoBean);
}
/**
* Check if the selected domain is available to register
*
* @param domainName dimaain name
* @return true, if the domain is avaialable to register
* @throws Exception, if unable to get the tenant manager, or get the tenant id
* from manager.
*/
public boolean checkDomainAvailability(String domainName) throws Exception {
TenantManager tenantManager = TenantMgtServiceComponent.getTenantManager();
int tenantId = tenantManager.getTenantId(domainName);
if (log.isDebugEnabled()) {
log.debug("Tenant Domain is available to register.");
}
return tenantId < 0; // no tenant exists with the same tenant domain
}
// use a boolean instead of string.
/**
* Validates or Suggests a domain.
*
* @param domain tenant domain
* @param successKey success key
* @return domain name
* @throws Exception if exception in validating or suggesting the tenant domain.
*/
public String validateOrSuggestDomain(String domain, String successKey) throws Exception {
if (successKey != null && !successKey.equals("")) {
if (CommonUtil.validateDomainFromSuccessKey(
TenantMgtServiceComponent.getGovernanceSystemRegistry(
MultitenantConstants.SUPER_TENANT_ID), domain, successKey)) {
return domain;
}
}
// otherwise domain is not correct
return "null";
}
/**
* Generates a random Captcha
*
* @return captchaInfoBean
* @throws Exception, if exception in cleaning old captchas or generating new
* captcha image.
*/
public CaptchaInfoBean generateRandomCaptcha() throws Exception {
// we will clean the old captchas asynchronously
CaptchaUtil.cleanOldCaptchas();
return CaptchaUtil.generateCaptchaImage();
}
/**
* To proceed updating credentials
*
* @param domain domain name to update the credentials
* @param confirmationKey confirmation key to verify the request.
* @return True, if successful in verifying and hence updating the
* credentials.
* @throws Exception, if confirmation key doesn't exist in the registry.
*/
public boolean proceedUpdateCredentials(String domain, String confirmationKey) throws Exception {
TenantManager tenantManager = TenantMgtServiceComponent.getTenantManager();
int tenantId;
try {
tenantId = tenantManager.getTenantId(domain);
} catch (UserStoreException e) {
String msg = "Error in getting tenant, tenant domain: " + domain + ".";
log.error(msg);
throw new RegistryException(msg, e);
}
UserRegistry superTenantSystemRegistry = TenantMgtServiceComponent
.getGovernanceSystemRegistry(MultitenantConstants.SUPER_TENANT_ID);
String adminManagementPath = StratosConstants.ADMIN_MANAGEMENT_FLAG_PATH +
RegistryConstants.PATH_SEPARATOR + tenantId;
Resource resource = null;
if (superTenantSystemRegistry.resourceExists(adminManagementPath)) {
resource = superTenantSystemRegistry.get(adminManagementPath);
String actualConfirmationKey = null;
Object content = resource.getContent();
if (content instanceof String) {
actualConfirmationKey = (String) content;
} else if (content instanceof byte[]) {
actualConfirmationKey = new String((byte[]) content);
}
if ((actualConfirmationKey != null) && (actualConfirmationKey.equals(confirmationKey))) {
if (log.isDebugEnabled()) {
log.debug("Password resetting by the tenant admin for the domain: " + domain);
}
return true;
} else if (actualConfirmationKey == null ||
!actualConfirmationKey.equals(confirmationKey)) {
// validation will fail
String msg = StratosConstants.CONFIRMATION_KEY_NOT_MACHING;
log.error(msg);
return false; // do not proceed
}
} else {
log.warn("The confirmationKey doesn't exist in service.");
}
if (resource == null) {
String msg = "Resource doesn't exist";
log.error(msg);
throw new Exception(msg);
} else if ((superTenantSystemRegistry.get(resource.getPath()) != null)) {
try {
superTenantSystemRegistry.delete(resource.getPath());
} catch (Exception e) {
String msg = "Unable to delete the resource";
log.error(msg, e);
throw new Exception(msg, e);
}
}
return false;
}
}