Skip to content

Commit

Permalink
Fixes #547
Browse files Browse the repository at this point in the history
  • Loading branch information
oharsta committed Dec 5, 2024
1 parent 3f51d64 commit 4b39896
Show file tree
Hide file tree
Showing 16 changed files with 246 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,25 @@ public class InstitutionMailUsage {
private final MailBox mailBox;
private final UserRepository userRepository;
private final boolean mailInstitutionMailUsage;
private final boolean cronJobResponsible;

@Autowired
public InstitutionMailUsage(Manage manage,
MailBox mailBox,
UserRepository userRepository,
@Value("${cron.node-cron-job-responsible}") boolean cronJobResponsible,
@Value("${feature.mail_institution_mail_usage}") boolean mailInstitutionMailUsage) {
this.manage = manage;
this.mailBox = mailBox;
this.userRepository = userRepository;
this.cronJobResponsible = cronJobResponsible;
this.mailInstitutionMailUsage = mailInstitutionMailUsage;
}

@Scheduled(cron = "${cron.mail-institution-mail-usage-expression}")
@SuppressWarnings("unchecked")
public void mailUsersWithInstitutionMail() {
if (!mailInstitutionMailUsage) {
if (!mailInstitutionMailUsage || !cronJobResponsible) {
return;
}
long start = System.currentTimeMillis();
Expand Down
65 changes: 65 additions & 0 deletions myconext-server/src/main/java/myconext/cron/NudgeAppMail.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package myconext.cron;

import myconext.mail.MailBox;
import myconext.manage.Manage;
import myconext.model.User;
import myconext.repository.UserRepository;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

@Component
public class NudgeAppMail {

private static final Log LOG = LogFactory.getLog(NudgeAppMail.class);

private final MailBox mailBox;
private final UserRepository userRepository;
private final boolean nudgeAppMailFeature;
private final boolean cronJobResponsible;
private final long nudgeAppMailDaysAfterCreation;

@Autowired
public NudgeAppMail(MailBox mailBox,
UserRepository userRepository,
@Value("${cron.node-cron-job-responsible}") boolean cronJobResponsible,
@Value("${cron.nudge-app-mail-days-after-creation}") long nudgeAppMailDaysAfterCreation,
@Value("${feature.nudge_app_mail}") boolean nudgeAppMailFeature) {
this.mailBox = mailBox;
this.userRepository = userRepository;
this.cronJobResponsible = cronJobResponsible;
this.nudgeAppMailDaysAfterCreation = nudgeAppMailDaysAfterCreation;
this.nudgeAppMailFeature = nudgeAppMailFeature;
}

@Scheduled(cron = "${cron.nudge-app-mail-expression}")
@SuppressWarnings("unchecked")
public void mailUsersWithoutApp() {
if (!nudgeAppMailFeature || !cronJobResponsible) {
return;
}
long start = System.currentTimeMillis();
try {
long createdBefore = (new Date().getTime() - (nudgeAppMailDaysAfterCreation * 24 * 60 * 60 * 1000)) / 1000;
List<User> users = userRepository.findByNoEduIDApp(createdBefore);

users.forEach(user -> {
mailBox.sendNudgeAppMail(user);
user.setNudgeAppMailSend(true);
userRepository.save(user);
});

LOG.info(String.format("Mailed %s users to nudge the app in %s ms",
users.size(), System.currentTimeMillis() - start));
} catch (Exception e) {
LOG.error("Error in mailUsersWithInstitutionMail", e);
}
}

}
7 changes: 7 additions & 0 deletions myconext-server/src/main/java/myconext/mail/MailBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ public void sendInstitutionMailWarning(User user) {
sendMail("institution_mail_warning", title, variables, preferredLanguage(user), user.getEmail(), false);
}

public void sendNudgeAppMail(User user) {
String title = this.getTitle("nudge_eduid_app", user);
Map<String, Object> variables = variables(user, title);
variables.put("mySurfConextURL", mySURFconextURL);
sendMail("nudge_eduid_app", title, variables, preferredLanguage(user), user.getEmail(), false);
}

public void sendResetPassword(User user, String hash, boolean mobileRequest) {
String title = this.getTitle("reset_password", user);
Map<String, Object> variables = variables(user, title);
Expand Down
3 changes: 3 additions & 0 deletions myconext-server/src/main/java/myconext/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ public class User implements Serializable, UserDetails {

private long created;
private long lastLogin;

@Setter
private boolean nudgeAppMailSend;
@Setter
@Indexed
private String trackingUuid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,19 @@ public interface UserRepository extends MongoRepository<User, String> {

@Query("{'email' : {$regex : ?0, $options: 'i'}}")
List<User> findByEmailDomain(String regex);


@Query("""
{ $and: [ { $or: [
{ 'surfSecureId': { $exists: false } },
{ 'surfSecureId': { $eq: {} } }
]},
{ $or: [
{ 'nudgeAppMailSend': false },
{ 'nudgeAppMailSend': { $exists: false } }
]},
{'created': { $lt: ?0 }}]}
""")
List<User> findByNoEduIDApp(Long createdBefore);

}
7 changes: 6 additions & 1 deletion myconext-server/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ cron:
manage-fixed-rate-milliseconds: 43_200_000
# Runs on the first day of February, May, August, and November.
mail-institution-mail-usage-expression: "0 0 0 1 2,5,8,11 *"
# Every day at 6:30AM
nudge-app-mail-expression: "0 30 6 * * ?"
# Number of days after creation of the eduID account which the nudge mail is send
nudge-app-mail-days-after-creation: 14

manage:
username: myconext
Expand Down Expand Up @@ -101,7 +105,8 @@ feature:
remote_creation_api: True
# Do we periodically mail users who have used their institution account
mail_institution_mail_usage: True

# Do we mail users who have not installed the eduID app
nudge_app_mail: True
secure_cookie: false
idp_entity_id: https://localhost.surf.id
private_key_path: classpath:/myconext.pem
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
completed your education, you will lose access to your eduID. While you can use your eduID after graduation.
That's why we recommend that you just use your own email. You can change your email address
in the <a href="{{mySurfConextURL}}">settings of your eduID account </a>.</p>
<br/>
<p>
Kind regards,
eduID.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Hi {{name}},

You have created an eduID with your institutional account. If you're using your institution account, and you have
completed your education, you will lose access to your eduID. While you can use your eduID after graduation.
That's why we recommend that you just use your own email. You can change your email address
in the {{mySurfConextURL}} settings of your eduID account
completed your education, you will lose access to your eduID. While you can use your eduID after graduation.
That's why we recommend that you just use your own email. You can change your email address
in the {{mySurfConextURL}} settings of your eduID account

{{> footer_en.txt}}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
<body>
<div class="main" style="font-family: Helvetica, Arial, sans-serif;line-height: 18px;font-size: 14px;color: #353535;">
<div class="head" style="background-color: #f5f5f5;padding: 30px 0 20px 60px;">
<p class="title" style="font-weight: 600;font-size: 38px;line-height: 38px; margin: 0;margin-bottom: 10px">You
have created an eduID with your institutional account</p>
<p class="title" style="font-weight: 600;font-size: 38px;line-height: 38px; margin: 0;margin-bottom: 10px">Je hebt een eduID aangemaakt met je instelling account</p>
</div>
<div class="middle" style="padding: 20px 0 40px 60px;max-width: 600px;">
<p>Hi <strong>{{name}}</strong>,</p>
Expand All @@ -16,6 +15,7 @@
opleiding weer kan gebruiken.
Daarom raden we je aan om gewoon je eigen e-mail te gebruiken. Je kunt in je
<a href="{{mySurfConextURL}}">instellingen van je eduID account</a> je e-mail adres wijzigen.</p>
<br/>
<p>
Kind regards,
eduID.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<div class="main" style="font-family: Helvetica, Arial, sans-serif;line-height: 18px;font-size: 14px;color: #353535;">
<div class="head" style="background-color: #f5f5f5;padding: 30px 0 20px 60px;">
<p class="title" style="font-weight: 600;font-size: 38px;line-height: 38px; margin: 0;margin-bottom: 10px">
Install the eduID app</p>
</div>
<div class="middle" style="padding: 20px 0 40px 60px;max-width: 600px;">
<p>Hi <strong>{{name}}</strong>,</p>
<p>You have created an eduID account, but have not installed the app. It is much more convenient if you install
the app, so you can log in faster. Go to <a href="{{mySurfConextURL}}">{{mySurfConextURL}}</a> to link
your account to your eduID app.</p>
<br/>
<p>
Kind regards,
eduID.
</p>
</div>
{{> footer_nl.html}}
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Hi {{name}},

You have created an eduID account, but have not installed the app. It is much more convenient if you install
the app, so you can log in faster. Go to {{mySurfConextURL}} to link your account to your eduID app.

{{> footer_en.txt}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<div class="main" style="font-family: Helvetica, Arial, sans-serif;line-height: 18px;font-size: 14px;color: #353535;">
<div class="head" style="background-color: #f5f5f5;padding: 30px 0 20px 60px;">
<p class="title" style="font-weight: 600;font-size: 38px;line-height: 38px; margin: 0;margin-bottom: 10px">You
have created an eduID with your institutional account</p>
</div>
<div class="middle" style="padding: 20px 0 40px 60px;max-width: 600px;">
<p>Hi <strong>{{name}}</strong>,</p>
<p>
Je hebt een eduID account aangemaakt maar de app niet geïnstalleerd. Het is super veel handiger als je de
app wel installeert, daarmee kan je sneller inloggen. Ga naar
<a href="{{mySurfConextURL}}">{{mySurfConextURL}}</a> om je account aan je eduID app te koppelen.

</p>
<br/>
<p>
Kind regards,
eduID.
</p>
</div>
{{> footer_nl.html}}
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Hoi {{name}},

Je hebt een eduID account aangemaakt maar de app niet geïnstalleerd. Het is super veel handiger als je de app wel
installeert, daarmee kan je sneller inloggen. Ga naar {{mySurfConextURL}} om je account aan je eduID app te koppelen.

Vriendelijke groetjes,
eduID.

{{> footer_nl.txt}}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
"institution_mail_warning": {
"en": "Warning: eduID institutional mail-account usage",
"nl": "Waarschuwing: eduID instellings e-mail gebruik"
},
"nudge_eduid_app": {
"en": "Installeer de eduID app",
"nl": "Install the eduID app"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,36 @@
import myconext.AbstractMailBoxTest;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
"mongodb_db=surf_id_test",
"cron.node-cron-job-responsible=true",
"email_guessing_sleep_millis=1",
"sp_entity_id=https://engine.test.surfconext.nl/authentication/sp/metadata",
"sp_entity_metadata_url=https://engine.test.surfconext.nl/authentication/sp/metadata",
"spring.main.lazy-initialization=true",
"eduid_api.oidcng_introspection_uri=http://localhost:8098/introspect",
"cron.service-name-resolver-initial-delay-milliseconds=60000",
"oidc.base-url=http://localhost:8098/",
"sso_mfa_duration_seconds=-1000",
"feature.requires_signed_authn_request=false",
"feature.deny_disposable_email_providers=false",
"verify.base_uri=http://localhost:8098"
})
public class InstitutionMailUsageTest extends AbstractMailBoxTest {

@Autowired
protected InstitutionMailUsage institutionMailUsage;

@Test
public void mailUsersWithInstitutionMail() throws MessagingException, IOException {
public void mailUsersWithInstitutionMail() {
institutionMailUsage.mailUsersWithInstitutionMail();

List<MimeMessage> mimeMessages = mailMessages();
Expand Down
48 changes: 48 additions & 0 deletions myconext-server/src/test/java/myconext/cron/NudgeAppMailTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package myconext.cron;

import myconext.AbstractIntegrationTest;
import myconext.AbstractMailBoxTest;
import myconext.model.User;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import javax.mail.internet.MimeMessage;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
"mongodb_db=surf_id_test",
"cron.node-cron-job-responsible=true",
"email_guessing_sleep_millis=1",
"sp_entity_id=https://engine.test.surfconext.nl/authentication/sp/metadata",
"sp_entity_metadata_url=https://engine.test.surfconext.nl/authentication/sp/metadata",
"spring.main.lazy-initialization=true",
"eduid_api.oidcng_introspection_uri=http://localhost:8098/introspect",
"cron.service-name-resolver-initial-delay-milliseconds=60000",
"oidc.base-url=http://localhost:8098/",
"sso_mfa_duration_seconds=-1000",
"feature.requires_signed_authn_request=false",
"feature.deny_disposable_email_providers=false",
"verify.base_uri=http://localhost:8098"
})
public class NudgeAppMailTest extends AbstractMailBoxTest {

@Autowired
protected NudgeAppMail nudgeAppMail;

@Test
public void mailUsersWithoutApp() {
nudgeAppMail.mailUsersWithoutApp();

List<MimeMessage> mimeMessages = mailMessages();

assertEquals(1, mimeMessages.size());

User mary = userRepository.findOneUserByEmail("[email protected]");
assertTrue(mary.isNudgeAppMailSend());
}

}

0 comments on commit 4b39896

Please sign in to comment.