Skip to content

Commit b780a44

Browse files
ReactiveOauth plus AbstractLemonService halfway
1 parent e4a3813 commit b780a44

File tree

12 files changed

+323
-300
lines changed

12 files changed

+323
-300
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
package com.naturalprogrammer.spring.lemon.commons;
2+
3+
import java.io.Serializable;
4+
import java.util.HashMap;
5+
import java.util.Map;
6+
7+
import org.apache.commons.lang3.exception.ExceptionUtils;
8+
import org.apache.commons.logging.Log;
9+
import org.apache.commons.logging.LogFactory;
10+
import org.springframework.boot.context.event.ApplicationReadyEvent;
11+
import org.springframework.context.event.EventListener;
12+
import org.springframework.security.crypto.password.PasswordEncoder;
13+
14+
import com.naturalprogrammer.spring.lemon.commons.LemonProperties.Admin;
15+
import com.naturalprogrammer.spring.lemon.commons.domain.LemonUser;
16+
import com.naturalprogrammer.spring.lemon.commons.mail.LemonMailData;
17+
import com.naturalprogrammer.spring.lemon.commons.mail.MailSender;
18+
import com.naturalprogrammer.spring.lemon.commons.security.BlueTokenService;
19+
import com.naturalprogrammer.spring.lemon.commons.security.GreenTokenService;
20+
import com.naturalprogrammer.spring.lemon.commons.util.LecUtils;
21+
import com.naturalprogrammer.spring.lemon.commons.util.UserUtils;
22+
import com.naturalprogrammer.spring.lemon.exceptions.util.LexUtils;
23+
24+
public abstract class AbstractLemonService
25+
<U extends LemonUser<ID>, ID extends Serializable> {
26+
27+
private static final Log log = LogFactory.getLog(AbstractLemonService.class);
28+
protected PasswordEncoder passwordEncoder;
29+
protected LemonProperties properties;
30+
protected BlueTokenService blueTokenService;
31+
protected GreenTokenService greenTokenService;
32+
protected MailSender mailSender;
33+
34+
/**
35+
* This method is called after the application is ready.
36+
* Needs to be public - otherwise Spring screams.
37+
*
38+
* @param event
39+
*/
40+
@EventListener
41+
public void afterApplicationReady(ApplicationReadyEvent event) {
42+
43+
log.info("Starting up Spring Lemon ...");
44+
onStartup(); // delegate to onStartup()
45+
log.info("Spring Lemon started");
46+
}
47+
48+
protected abstract void onStartup();
49+
50+
/**
51+
* Creates the initial Admin user.
52+
* Override this if needed.
53+
*/
54+
protected U createAdminUser() {
55+
56+
// fetch data about the user to be created
57+
Admin initialAdmin = properties.getAdmin();
58+
59+
log.info("Creating the first admin user: " + initialAdmin.getUsername());
60+
61+
// create the user
62+
U user = newUser();
63+
user.setEmail(initialAdmin.getUsername());
64+
user.setPassword(passwordEncoder.encode(
65+
properties.getAdmin().getPassword()));
66+
user.getRoles().add(UserUtils.Role.ADMIN);
67+
68+
return user;
69+
}
70+
71+
protected abstract U newUser();
72+
73+
protected Map<String, Object> buildContext() {
74+
75+
// make the context
76+
Map<String, Object> sharedProperties = new HashMap<String, Object>(2);
77+
sharedProperties.put("reCaptchaSiteKey", properties.getRecaptcha().getSitekey());
78+
sharedProperties.put("shared", properties.getShared());
79+
80+
Map<String, Object> context = new HashMap<>();
81+
context.put("context", sharedProperties);
82+
83+
return context;
84+
}
85+
86+
protected void initUser(U user) {
87+
88+
log.debug("Initializing user: " + user);
89+
90+
user.setPassword(passwordEncoder.encode(user.getPassword())); // encode the password
91+
makeUnverified(user); // make the user unverified
92+
}
93+
94+
/**
95+
* Makes a user unverified
96+
*/
97+
protected void makeUnverified(U user) {
98+
99+
user.getRoles().add(UserUtils.Role.UNVERIFIED);
100+
user.setCredentialsUpdatedMillis(System.currentTimeMillis());
101+
}
102+
103+
/**
104+
* Sends verification mail to a unverified user.
105+
*/
106+
protected void sendVerificationMail(final U user) {
107+
try {
108+
109+
log.debug("Sending verification mail to: " + user);
110+
111+
String verificationCode = greenTokenService.createToken(GreenTokenService.VERIFY_AUDIENCE,
112+
user.getId().toString(), properties.getJwt().getExpirationMillis(),
113+
LecUtils.mapOf("email", user.getEmail()));
114+
115+
// make the link
116+
String verifyLink = properties.getApplicationUrl()
117+
+ "/users/" + user.getId() + "/verification?code=" + verificationCode;
118+
119+
// send the mail
120+
sendVerificationMail(user, verifyLink);
121+
122+
log.debug("Verification mail to " + user.getEmail() + " queued.");
123+
124+
} catch (Throwable e) {
125+
// In case of exception, just log the error and keep silent
126+
log.error(ExceptionUtils.getStackTrace(e));
127+
}
128+
}
129+
130+
/**
131+
* Sends verification mail to a unverified user.
132+
* Override this method if you're using a different MailData
133+
*/
134+
protected void sendVerificationMail(final U user, String verifyLink) {
135+
136+
// send the mail
137+
mailSender.send(LemonMailData.of(user.getEmail(),
138+
LexUtils.getMessage("com.naturalprogrammer.spring.verifySubject"),
139+
LexUtils.getMessage(
140+
"com.naturalprogrammer.spring.verifyEmail", verifyLink)));
141+
}
142+
143+
/**
144+
* Mails the forgot password link.
145+
*
146+
* @param user
147+
*/
148+
public void mailForgotPasswordLink(U user) {
149+
150+
log.debug("Mailing forgot password link to user: " + user);
151+
152+
String forgotPasswordCode = greenTokenService.createToken(
153+
GreenTokenService.FORGOT_PASSWORD_AUDIENCE,
154+
user.getEmail(), properties.getJwt().getExpirationMillis());
155+
156+
// make the link
157+
String forgotPasswordLink = properties.getApplicationUrl()
158+
+ "/reset-password?code=" + forgotPasswordCode;
159+
160+
mailForgotPasswordLink(user, forgotPasswordLink);
161+
162+
log.debug("Forgot password link mail queued.");
163+
}
164+
165+
166+
/**
167+
* Mails the forgot password link.
168+
*
169+
* Override this method if you're using a different MailData
170+
*/
171+
public void mailForgotPasswordLink(U user, String forgotPasswordLink) {
172+
173+
// send the mail
174+
mailSender.send(LemonMailData.of(user.getEmail(),
175+
LexUtils.getMessage("com.naturalprogrammer.spring.forgotPasswordSubject"),
176+
LexUtils.getMessage("com.naturalprogrammer.spring.forgotPasswordEmail",
177+
forgotPasswordLink)));
178+
}
179+
180+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package com.naturalprogrammer.spring.lemon.commons.domain;
2+
3+
import java.io.Serializable;
4+
import java.util.Set;
5+
6+
public interface LemonUser<ID extends Serializable> {
7+
8+
void setEmail(String username);
9+
void setPassword(String password);
10+
Set<String> getRoles();
11+
String getPassword();
12+
void setCredentialsUpdatedMillis(long currentTimeMillis);
13+
ID getId();
14+
String getEmail();
15+
16+
}

spring-lemon-jpa/src/main/java/com/naturalprogrammer/spring/lemon/LemonAutoConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ public LemonAuthenticationSuccessHandler authenticationSuccessHandler(
7676
*/
7777
@Bean
7878
@ConditionalOnMissingBean(OAuth2AuthenticationSuccessHandler.class)
79-
public OAuth2AuthenticationSuccessHandler<?> oauth2AuthenticationSuccessHandler(
79+
public OAuth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler(
8080
LemonProperties properties, BlueTokenService blueTokenService) {
8181

8282
log.info("Configuring OAuth2AuthenticationSuccessHandler");
83-
return new OAuth2AuthenticationSuccessHandler<>(properties, blueTokenService);
83+
return new OAuth2AuthenticationSuccessHandler(properties, blueTokenService);
8484
}
8585

8686
/**

0 commit comments

Comments
 (0)