All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jk.webstack.services.account.AccountServices Maven / Gradle / Ivy

/*
 * Copyright 2002-2022 Dr. Jalal Kiswani. 
 * Email: [email protected]
 * Check out https://smart-api.com for more details
 * 
 * All the opensource projects of Dr. Jalal Kiswani are free for personal and academic use only, 
 * for commercial usage and support, please contact the author.
 *
 * 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 com.jk.webstack.services.account;

import java.util.Date;
import java.util.Map;
import java.util.UUID;

import org.junit.Assert;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import com.jk.core.exceptions.JKInvalidTokenException;
import com.jk.core.factory.JKFactory;
import com.jk.core.logging.JKLogger;
import com.jk.core.logging.JKLoggerFactory;
import com.jk.core.security.JKPasswordUtil;
import com.jk.core.security.JKSecurityUtil;
import com.jk.core.templates.JKTemplateUtil;
import com.jk.core.util.JK;
import com.jk.core.util.JKValidationUtil;
import com.jk.data.dataaccess.orm.JKObjectDataAccess;
import com.jk.data.dataaccess.orm.JKObjectDataAccessImpl;
import com.jk.data.exceptions.JKRecordNotFoundException;
import com.jk.web.util.JKWebUtil;
import com.jk.webstack.services.email.EmailService;

// TODO: Auto-generated Javadoc
/**
 * The Class AccountServices.
 */
public class AccountServices implements UserDetailsService {
	
	/** The logger. */
	static JKLogger logger = JKLoggerFactory.getLogger(AccountServices.class);

	/** The data access service. */
	JKObjectDataAccess dataAccessService = JKFactory.instance(JKObjectDataAccessImpl.class);
	
	/** The email service. */
	EmailService emailService = new EmailService();

	/**
	 * Instantiates a new account services.
	 */
	//////////////////////////////////////////////////////////////////
	public AccountServices() {
	}

	/**
	 * Load user by username.
	 *
	 * @param username the username
	 * @return the account
	 * @throws UsernameNotFoundException the username not found exception
	 */
	//////////////////////////////////////////////////////////////////
	@Override
	public Account loadUserByUsername(String username) throws UsernameNotFoundException {
		Account account = findAccountByEmail(username);
		if (account == null) {
			throw new UsernameNotFoundException(username);
		}
		return account;
	}

	/**
	 * Creates the account.
	 *
	 * @param email the email
	 * @param firstname the firstname
	 * @param lastname the lastname
	 * @param password the password
	 * @return the account
	 * @throws AccountAlreadyExistsException the account already exists exception
	 */
	//////////////////////////////////////////////////////////////////
	public Account createAccount(String email, String firstname, String lastname, String password) throws AccountAlreadyExistsException {
		logger.debug("Create account with ({},{},{})", email, firstname, lastname);
		Account account = findAccountByEmail(email);
		if (account == null) {
			account = Account.create().email(email).firstname(firstname).lastname(lastname);
			account.setTemp(password);
			processNewAccount(account);
		} else {
			//account.setTemp(password);
			//processCurrentAccount(account);
			throw new AccountAlreadyExistsException();
		}
		return account;
	}

	/**
	 * Process new account.
	 *
	 * @param account the account
	 */
	//////////////////////////////////////////////////////////////////
	protected void processNewAccount(Account account) {
		logger.debug("Process new account ({})", account.getEmail());
		String password = account.getTemp();
		boolean sendWelcomeEmail = false;
		if (JKValidationUtil.isEmpty(password)) {
			password = JKPasswordUtil.generateNumricPassword(10);
			account.setTemp(password);
			sendWelcomeEmail = true;
		}
		account.setPassword(JKWebUtil.encodePassword(password));
		createToken(account);
		dataAccessService.insert(account);
		logger.debug("Account created ({}) with password ({})", account.getEmail(), account.getPassword());
		if (sendWelcomeEmail) {
			sendWelcomeEmail(account, password);
		}
	}

	/**
	 * Process current account.
	 *
	 * @param account the account
	 */
	//////////////////////////////////////////////////////////////////
	protected void processCurrentAccount(Account account) {
		resetAccount(account);
	}

	/**
	 * Reset account.
	 *
	 * @param email the email
	 * @return the account
	 */
	//////////////////////////////////////////////////////////////////
	public Account resetAccount(String email) {
		Account acconut = findAccountByEmail(email);
		if (acconut != null) {
			resetAccount(acconut);
			return acconut;
		} else {
			throw new JKRecordNotFoundException();
		}
	}

	/**
	 * Reset account.
	 *
	 * @param account the account
	 */
	//////////////////////////////////////////////////////////////////
	protected void resetAccount(Account account) {
		logger.debug("Reset account ({})", account.getEmail());
		String password = account.getTemp();
		boolean sendResetEmail = false;
//		if (JKValidationUtil.isEmpty(password)) {
			password = JKPasswordUtil.generateNumricPassword(10);
			account.setTemp(password);
			sendResetEmail = true;
//		}
		account.setPassword(new BCryptPasswordEncoder().encode(password));
		createToken(account);
		dataAccessService.update(account);
		if (sendResetEmail) {
			sendResetEmail(account, password);
		}
	}

	/**
	 * Send reset email.
	 *
	 * @param account the account
	 * @param password the password
	 */
	//////////////////////////////////////////////////////////////////
	private void sendResetEmail(Account account, String password) {
		Map map = JK.toMap("firstname", account.getFirstname(), "password", password, "link", createLoginLink(account));
		String emailContents = JKTemplateUtil.compile("/templates/email", "reset_account.ftl", map);
		emailService.addEmailToQueue(account.getEmail(), "Reset Password from Clowiz (the Cloud-Wizard)", emailContents,
				true);
	}

	/**
	 * Send welcome email.
	 *
	 * @param account the account
	 * @param password the password
	 */
	//////////////////////////////////////////////////////////////////
	private void sendWelcomeEmail(Account account, String password) {
		Map map = JK.toMap("firstname", account.getFirstname(), "password", password, "link", createLoginLink(account));
		logger.debug("Send welcome email with params({})", map);
		String emailContents = JKTemplateUtil.compile("/templates/email", "welcome-account.ftl", map);
		emailService.addEmailToQueue(account.getEmail(), "Welcome to Clowiz (the Cloud-Wizard)", emailContents, true);
	}

	/**
	 * Creates the login link.
	 *
	 * @param account the account
	 * @return the string
	 */
	//////////////////////////////////////////////////////////////////
	protected String createLoginLink(Account account) {
		String email = account.getEmail();
		String token = account.getOneTimeToken();
		String param = JKSecurityUtil.encode(email + "," + token);
		String url = String.format("https://www.clowiz.com/login2?ac=%s", param);
		return url;
	}

	/**
	 * Load details by token.
	 *
	 * @param tokenString the token string
	 * @return the account
	 */
	//////////////////////////////////////////////////////////////////
	public Account loadDetailsByToken(String tokenString) {
		String decode = null;
		try {
			decode = JKSecurityUtil.decode(tokenString);
		} catch (java.lang.IllegalArgumentException e) {
			throw new JKInvalidTokenException("Invalid token structure");
		}
		String[] data = decode.split(",");
		if (data.length != 2) {
			throw new JKInvalidTokenException("Invalid token structure");
		}
		String email = data[0];
		String tokenValue = data[1];

		Account account = findAccountByEmail(email);
		try {
			if (account == null) {
				throw new JKInvalidTokenException("Email is not valid:" + email);
			}
			if (account.getOneTimeToken() != null && account.getOneTimeToken().equals(tokenValue)
					&& !account.isTokenExpired()) {
				return account;
			}
			throw new JKInvalidTokenException("Token is not valid :" + tokenValue);
		} finally {
			resetToken(account);
		}
	}

	/**
	 * Reset token.
	 *
	 * @param account the account
	 */
	//////////////////////////////////////////////////////////////////
	protected void resetToken(Account account) {
		account.setOneTimeToken(null);
		dataAccessService.update(account);
	}

	/**
	 * Creates the token.
	 *
	 * @param account the account
	 */
	//////////////////////////////////////////////////////////////////
	protected void createToken(Account account) {
		// verify if this called by the right entity
		UUID uuid = UUID.nameUUIDFromBytes(account.getPassword().getBytes());
		account.setOneTimeToken(uuid.toString());
		account.setOneTokenTime(new Date());
	}

	/**
	 * The main method.
	 *
	 * @param args the arguments
	 */
	/////////////////////////////////////////////////////////////////
	public static void main(String[] args) {
		AccountServices service = new AccountServices();
//		service.createAccount("[email protected]", "Jalal", "Kiswani", null);
	}

	/**
	 * Sets the email verified.
	 *
	 * @param account the new email verified
	 */
	/////////////////////////////////////////////////////////////////
	public void setEmailVerified(Account account) {
		Map map = JK.toMap("verified_email", true);
//		dataAccessService.updateFields(Account.class, account.getId(), map);
	}

	/**
	 * Find account by email.
	 *
	 * @param email the email
	 * @return the account
	 */
	//////////////////////////////////////////////////////////////////
	protected Account findAccountByEmail(String email) {
		return dataAccessService.findOneByFieldName(Account.class, "email", email);
	}

	/**
	 * Change password.
	 *
	 * @param userName the user name
	 * @param currentPassword the current password
	 * @param newPassword the new password
	 */
	//////////////////////////////////////////////////////////////////
	public void changePassword(String userName, String currentPassword, String newPassword) {
		Account account = findAccountByEmail(userName);
		Assert.assertTrue(account != null);
		Assert.assertTrue(JKWebUtil.matchPasswords(currentPassword, account.getPassword()));
		account.setPassword(JKWebUtil.encodePassword(newPassword));
		dataAccessService.update(account);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy