com.kryshchuk.imcollector.auth.provider.SimpleAuthProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of imcollector-auth Show documentation
Show all versions of imcollector-auth Show documentation
Authentication module for imcollector platform
The newest version!
/*
* imcollector Authentication
* Copyright (C) 2013 Yuriy Kryshchuk
*
* 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, either version 3 of the License, or
* (at your option) any later version.
*
* 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 .
*/
package com.kryshchuk.imcollector.auth.provider;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import play.Application;
import play.data.Form;
import play.i18n.Lang;
import play.i18n.Messages;
import play.mvc.Call;
import play.mvc.Http.Context;
import com.feth.play.module.mail.Mailer.Mail.Body;
import com.feth.play.module.pa.PlayAuthenticate;
import com.feth.play.module.pa.providers.password.UsernamePasswordAuthProvider;
import com.kryshchuk.imcollector.auth.LinkedAccount;
import com.kryshchuk.imcollector.auth.TokenType;
import com.kryshchuk.imcollector.auth.User;
import com.kryshchuk.imcollector.auth.UserNotFoundException;
import com.kryshchuk.imcollector.auth.dao.AuthFactoryBuilder;
import com.kryshchuk.imcollector.auth.dao.UserDAO;
import com.kryshchuk.imcollector.auth.form.SimpleLogin;
import com.kryshchuk.imcollector.auth.form.SimpleSignup;
/**
* @author yura
* @since 1.0
*/
public abstract class SimpleAuthProvider extends
UsernamePasswordAuthProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleAuthProvider.class);
private static final String SETTING_KEY_VERIFICATION_LINK_SECURE = SETTING_KEY_MAIL + "." + "verificationLink.secure";
private static final String SETTING_KEY_PASSWORD_RESET_LINK_SECURE = SETTING_KEY_MAIL + "."
+ "passwordResetLink.secure";
private static final String SETTING_KEY_LINK_LOGIN_AFTER_PASSWORD_RESET = "loginAfterPasswordReset";
private static final String EMAIL_TEMPLATE_FALLBACK_LANGUAGE = "en";
public SimpleAuthProvider(final Application app) {
super(app);
LOGGER.trace("Instantiated");
}
public static SimpleAuthProvider getProvider() {
return (SimpleAuthProvider) PlayAuthenticate.getProvider(UsernamePasswordAuthProvider.PROVIDER_KEY);
}
@Override
protected List neededSettingKeys() {
final List needed = new ArrayList<>(super.neededSettingKeys());
needed.add(SETTING_KEY_VERIFICATION_LINK_SECURE);
needed.add(SETTING_KEY_PASSWORD_RESET_LINK_SECURE);
needed.add(SETTING_KEY_LINK_LOGIN_AFTER_PASSWORD_RESET);
return needed;
}
public boolean isLoginAfterPasswordReset() {
return getConfiguration().getBoolean(SETTING_KEY_LINK_LOGIN_AFTER_PASSWORD_RESET);
}
@Override
protected SimpleLoginAuthUser buildLoginAuthUser(final SimpleLogin login, final Context ctx) {
return new SimpleLoginAuthUser(login);
}
@Override
protected SimpleSignupAuthUser buildSignupAuthUser(final SimpleSignup signup, final Context ctx) {
return new SimpleSignupAuthUser(signup);
}
@Override
protected String generateVerificationRecord(final SimpleSignupAuthUser user) {
try {
final UserDAO dao = AuthFactoryBuilder.getFactory().getUserDAO();
return generateVerificationRecord(dao.find(user));
} catch (final UserNotFoundException e) {
LOGGER.error("Could not generate verification record for {}", user, e);
return generateToken();
}
}
protected String generateVerificationRecord(final User user) {
final String token = generateToken();
// Do database actions, etc.
AuthFactoryBuilder.getFactory().getTokenActionDAO().create(TokenType.EMAIL_VERIFICATION, token, user);
return token;
}
@Override
protected Form getLoginForm() {
return SimpleLogin.LOGIN_FORM;
}
@Override
protected Form getSignupForm() {
return SimpleSignup.FORM;
}
@Override
protected Body getVerifyEmailMailingBody(final String token, final SimpleSignupAuthUser user, final Context ctx) {
final boolean isSecure = getConfiguration().getBoolean(SETTING_KEY_VERIFICATION_LINK_SECURE);
final String url = getAccountVerifyCall(token).absoluteURL(ctx.request(), isSecure);
final Lang lang = Lang.preferred(ctx.request().acceptLanguages());
final String langCode = lang.code();
final String html = getEmailTemplate("views.html.account.email.verify_email", langCode, url, token, user.getName(),
user.getEmail());
final String text = getEmailTemplate("views.txt.account.email.verify_email", langCode, url, token, user.getName(),
user.getEmail());
return new Body(text, html);
}
@Override
protected String getVerifyEmailMailingSubject(final SimpleSignupAuthUser user, final Context ctx) {
return Messages.get("imcollector.auth.email.subject.verify_email");
}
protected abstract Call getAccountVerifyCall(String token);
@Override
protected UsernamePasswordAuthProvider.LoginResult loginUser(final SimpleLoginAuthUser authUser) {
try {
final UserDAO dao = AuthFactoryBuilder.getFactory().getUserDAO();
final User u = dao.find(authUser);
if (!u.isEmailValidated()) {
return LoginResult.USER_UNVERIFIED;
} else {
for (final LinkedAccount acc : u.getLinkedAccounts()) {
if (getKey().equals(acc.getProvider())) {
if (authUser.checkPassword(acc.getUserId(), authUser.getPassword())) {
// Password was correct
return LoginResult.USER_LOGGED_IN;
} else {
// if you don't return here,
// you would allow the user to have
// multiple passwords defined
// usually we don't want this
return LoginResult.WRONG_PASSWORD;
}
}
}
return LoginResult.WRONG_PASSWORD;
}
} catch (final UserNotFoundException e) {
return LoginResult.NOT_FOUND;
}
}
@Override
protected UsernamePasswordAuthProvider.SignupResult signupUser(final SimpleSignupAuthUser user) {
final UserDAO dao = AuthFactoryBuilder.getFactory().getUserDAO();
try {
final User u = dao.find(user);
if (u.isEmailValidated()) {
// This user exists, has its email validated and is active
return SignupResult.USER_EXISTS;
} else {
// this user exists, is active but has not yet validated its
// email
return SignupResult.USER_EXISTS_UNVERIFIED;
}
} catch (final UserNotFoundException e) {
// The user either does not exist or is inactive - create a new one
final User newUser = dao.create(user);
LOGGER.debug("New user created {}", newUser);
// Usually the email should be verified before allowing login, however
// if you return
// return SignupResult.USER_CREATED;
// then the user gets logged in directly
return SignupResult.USER_CREATED_UNVERIFIED;
}
}
@Override
protected SimpleLoginAuthUser transformAuthUser(final SimpleSignupAuthUser authUser, final Context context) {
return new SimpleLoginAuthUser(authUser.getEmail());
}
private Class> loadTemplateClass(final String templateClassName) throws ClassNotFoundException {
return Thread.currentThread().getContextClassLoader().loadClass(templateClassName);
}
private Class> findTemplateClass(final String template, final String lang) {
try {
return loadTemplateClass(template + "_" + lang);
} catch (final ClassNotFoundException e) {
LOGGER.warn("Template {} could not be found in requested language {}", template, lang);
try {
return loadTemplateClass(template + "_" + EMAIL_TEMPLATE_FALLBACK_LANGUAGE);
} catch (final ClassNotFoundException ee) {
LOGGER.error("Template {} could not be found in fallback language {}", template,
EMAIL_TEMPLATE_FALLBACK_LANGUAGE);
return null;
}
}
}
private String getEmailTemplate(final String template, final String langCode, final String url, final String token,
final String name, final String email) {
final Class> cls = findTemplateClass(template, langCode);
if (cls == null) {
throw new IllegalArgumentException("No email template available for " + template);
} else {
try {
final Method htmlRender = cls.getMethod("render", String.class, String.class, String.class, String.class);
return htmlRender.invoke(null, url, token, name, email).toString();
} catch (final Exception e) {
LOGGER.error("Cannot invoke render for emailTemplate {}", template, e);
throw new IllegalStateException("Failed to render email template", e);
}
}
}
public void sendPasswordResetMailing(final User user, final Context ctx) {
final String token = generatePasswordResetRecord(user);
final String subject = getPasswordResetMailingSubject(user, ctx);
final Body body = getPasswordResetMailingBody(token, user, ctx);
sendMail(subject, body, getEmailName(user));
}
public void sendVerifyEmailMailingAfterSignup(final User user, final Context ctx) {
final String subject = getVerifyEmailMailingSubjectAfterSignup(user, ctx);
final String token = generateVerificationRecord(user);
final Body body = getVerifyEmailMailingBodyAfterSignup(token, user, ctx);
sendMail(subject, body, getEmailName(user));
}
private Body getVerifyEmailMailingBodyAfterSignup(final String token, final User user, final Context ctx) {
final boolean isSecure = getConfiguration().getBoolean(SETTING_KEY_VERIFICATION_LINK_SECURE);
final String url = getAccountVerifyCall(token).absoluteURL(ctx.request(), isSecure);
final Lang lang = Lang.preferred(ctx.request().acceptLanguages());
final String langCode = lang.code();
final String html = getEmailTemplate("views.html.account.email.verify_email", langCode, url, token, user.getName(),
user.getEmail());
final String text = getEmailTemplate("views.txt.account.email.verify_email", langCode, url, token, user.getName(),
user.getEmail());
return new Body(text, html);
}
private String getVerifyEmailMailingSubjectAfterSignup(final User user, final Context ctx) {
return Messages.get("imcollector.auth.email.subject.verify_signup");
}
private Body getPasswordResetMailingBody(final String token, final User user, final Context ctx) {
final boolean isSecure = getConfiguration().getBoolean(SETTING_KEY_PASSWORD_RESET_LINK_SECURE);
final String url = getAccountResetPasswordCall(token).absoluteURL(ctx.request(), isSecure);
final Lang lang = Lang.preferred(ctx.request().acceptLanguages());
final String langCode = lang.code();
final String html = getEmailTemplate("views.html.account.email.password_reset", langCode, url, token,
user.getName(), user.getEmail());
final String text = getEmailTemplate("views.txt.account.email.password_reset", langCode, url, token,
user.getName(), user.getEmail());
return new Body(text, html);
}
protected abstract Call getAccountResetPasswordCall(String token);
private String getPasswordResetMailingSubject(final User user, final Context ctx) {
return Messages.get("imcollector.auth.email.subject.password_reset");
}
private String getEmailName(final User user) {
return getEmailName(user.getEmail(), user.getName());
}
private String generatePasswordResetRecord(final User user) {
final String token = generateToken();
AuthFactoryBuilder.getFactory().getTokenActionDAO().create(TokenType.PASSWORD_RESET, token, user);
return token;
}
private static String generateToken() {
return UUID.randomUUID().toString();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy