Testing mail with jetty jndi.
Change-Id: If4393b189e1eaa4380cbccfc8e126e336d122945
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
index 46649eb..564832c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
@@ -139,6 +139,8 @@
//EM:copied from EntityDao
KorAPUser user = new KorAPUser(); // oder eigentlich new DemoUser oder new DefaultUser.
user.setUsername(username);
+ // get user data
+ user.setEmail(config.getTestEmail());
return user;
// return entHandler.getAccount(username);
}
@@ -215,9 +217,9 @@
return;
}
- if (headerMap != null && headerMap.containsKey(org.eclipse.jetty.http.HttpHeaders.X_FORWARDED_FOR)) {
+ if (headerMap != null && headerMap.containsKey(com.google.common.net.HttpHeaders.X_FORWARDED_FOR)) {
- String[] vals = headerMap.getFirst(org.eclipse.jetty.http.HttpHeaders.X_FORWARDED_FOR).split(",");
+ String[] vals = headerMap.getFirst(com.google.common.net.HttpHeaders.X_FORWARDED_FOR).split(",");
String clientAddress = vals[0];
try {
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
index 7b9c48c..ad6aaab 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
@@ -14,6 +14,13 @@
*/
public class FullConfiguration extends KustvaktConfiguration {
+ // mail configuration
+ private boolean isMailEnabled;
+ private String testEmail;
+ private String mailUsername;
+ private String mailPassword;
+ private String mailSmtp;
+ private String mailPort;
private String ldapConfig;
@@ -49,12 +56,28 @@
// EM: pattern for matching availability in Krill matches
setLicensePatterns(properties);
setDeleteConfiguration(properties);
+ setMailConfiguration(properties);
ldapConfig = properties.getProperty("ldap.config");
+
+ }
+
+ private void setMailConfiguration (Properties properties) {
+ setMailEnabled(Boolean.valueOf(properties.getProperty("mail.enabled", "false")));
+ setTestEmail(properties.getProperty("mail.receiver"));
+ if (isMailEnabled){
+ // other properties must be set in the kustvakt.conf
+ setMailUsername(properties.getProperty("mail.username"));
+ setMailPassword(properties.getProperty("mail.password"));
+ setMailSmtp(properties.getProperty("mail.smtp"));
+ setMailPort(properties.getProperty("mail.port"));
+ }
}
private void setDeleteConfiguration (Properties properties) {
- setSoftDeleteGroup(parseDeleteConfig(properties.getProperty("delete.group", "")));
- setSoftDeleteAutoGroup(parseDeleteConfig(properties.getProperty("delete.auto.group", "")));
+ setSoftDeleteGroup(
+ parseDeleteConfig(properties.getProperty("delete.group", "")));
+ setSoftDeleteAutoGroup(parseDeleteConfig(
+ properties.getProperty("delete.auto.group", "")));
setSoftDeleteGroupMember(parseDeleteConfig(
properties.getProperty("delete.group.member", "")));
}
@@ -217,4 +240,52 @@
this.isSoftDeleteAutoGroup = isSoftDeleteAutoGroup;
}
+ public String getTestEmail () {
+ return testEmail;
+ }
+
+ public void setTestEmail (String testEmail) {
+ this.testEmail = testEmail;
+ }
+
+ public String getMailUsername () {
+ return mailUsername;
+ }
+
+ public void setMailUsername (String mailUsername) {
+ this.mailUsername = mailUsername;
+ }
+
+ public String getMailPassword () {
+ return mailPassword;
+ }
+
+ public void setMailPassword (String mailPassword) {
+ this.mailPassword = mailPassword;
+ }
+
+ public String getMailSmtp () {
+ return mailSmtp;
+ }
+
+ public void setMailSmtp (String mailHost) {
+ this.mailSmtp = mailHost;
+ }
+
+ public String getMailPort () {
+ return mailPort;
+ }
+
+ public void setMailPort (String mailPort) {
+ this.mailPort = mailPort;
+ }
+
+ public boolean isMailEnabled () {
+ return isMailEnabled;
+ }
+
+ public void setMailEnabled (boolean isMailEnabled) {
+ this.isMailEnabled = isMailEnabled;
+ }
+
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
index 4b3a6d6..6871205 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktServer.java
@@ -1,6 +1,22 @@
package de.ids_mannheim.korap.server;
-import de.ids_mannheim.korap.config.BeansFactory;
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URL;
+import java.util.Properties;
+
+import javax.naming.NamingException;
+
+import org.eclipse.jetty.jndi.factories.MailSessionReference;
+import org.eclipse.jetty.plus.jndi.Resource;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.webapp.Configuration.ClassList;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+import de.ids_mannheim.korap.config.FullConfiguration;
import de.ids_mannheim.korap.web.KustvaktBaseServer;
/**
@@ -11,17 +27,35 @@
*/
public class KustvaktServer extends KustvaktBaseServer {
+ private static FullConfiguration fullConfig;
+
public static final String API_VERSION = "v0.1";
public static void main (String[] args) throws Exception {
KustvaktServer server = new KustvaktServer();
kargs = server.readAttributes(args);
+
+ File f = new File("kustvakt.conf");
+ if (!f.exists()){
+ URL url = KustvaktServer.class.getClassLoader().getResource("kustvakt.conf");
+ if (url!=null){
+ f = new File(url.toURI());
+ }
+ }
+
+ Properties properties = new Properties();
+ FileInputStream in = new FileInputStream(f);
+ properties.load(in);
+ in.close();
+ fullConfig = new FullConfiguration(properties);
+ config = fullConfig;
- if (kargs.getConfig() != null)
- BeansFactory.loadFileContext(kargs.getConfig());
- else{
+ if (kargs.getConfig() == null){
+// BeansFactory.loadFileContext(kargs.getConfig());
+// }
+// else {
kargs.setConfig("default-config.xml");
- BeansFactory.loadClasspathContext("default-config.xml");
+// BeansFactory.loadClasspathContext("default-config.xml");
}
kargs.setRootPackages(new String[] { "de.ids_mannheim.korap.web.utils",
"de.ids_mannheim.korap.web.service.full" });
@@ -31,52 +65,30 @@
}
@Override
- protected void setup () {
-// Set<Class<? extends BootableBeanInterface>> set = KustvaktClassLoader
-// .loadSubTypes(BootableBeanInterface.class);
-//
-// ContextHolder context = BeansFactory.getKustvaktContext();
-// if (context == null)
-// throw new RuntimeException("Beans could not be loaded!");
-//
-// List<BootableBeanInterface> list = new ArrayList<>(set.size());
-// for (Class cl : set) {
-// BootableBeanInterface iface;
-//
-// try {
-// iface = (BootableBeanInterface) cl.newInstance();
-// if (iface instanceof CollectionLoader){
-// continue;
-// }
-// list.add(iface);
-// }
-// catch (InstantiationException | IllegalAccessException e) {
-// continue;
-// }
-// }
-// System.out.println("Found boot loading interfaces: " + list);
-//
-// while (!list.isEmpty()) {
-// loop: for (BootableBeanInterface iface : new ArrayList<>(list)) {
-// try {
-// for (Class dep : iface.getDependencies()) {
-// if (set.contains(dep))
-// continue loop;
-// }
-// iface.load(context);
-// list.remove(iface);
-// set.remove(iface.getClass());
-// System.out.println("Done with interface "
-// + iface.getClass().getSimpleName());
-// }
-// catch (KustvaktException e) {
-// // don't do anything!
-// System.out.println("An error occurred in class "
-// + iface.getClass().getSimpleName() + "!\n");
-// e.printStackTrace();
-// System.exit(-1);
-// }
-// }
-// }
+ protected void setupJndi(Server server, WebAppContext webapp) {
+
+
+// ClassList classlist = ClassList.setServerDefault(server);
+// classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
+// "org.eclipse.jetty.plus.webapp.EnvConfiguration",
+// "org.eclipse.jetty.plus.webapp.PlusConfiguration");
+
+ MailSessionReference mailref = new MailSessionReference();
+ mailref.setUser(fullConfig.getMailUsername());
+ mailref.setPassword(fullConfig.getMailPassword());
+
+ Properties props = new Properties();
+ props.put("mail.smtp.auth", "false");
+ props.put("mail.smtp.host",fullConfig.getMailSmtp());
+ props.put("mail.from",fullConfig.getMailUsername());
+ props.put("mail.debug", "false");
+ mailref.setProperties(props);
+ try {
+ new Resource(webapp, "mail/Session", mailref);
+ }
+ catch (NamingException e) {
+ e.printStackTrace();
+ }
}
+
}
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/MailService.java b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
new file mode 100644
index 0000000..74164d5
--- /dev/null
+++ b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
@@ -0,0 +1,63 @@
+package de.ids_mannheim.korap.service;
+
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.springframework.mail.javamail.MimeMessagePreparator;
+import org.springframework.stereotype.Service;
+
+import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
+import de.ids_mannheim.korap.user.User;
+
+@Service
+public class MailService {
+ @Autowired
+ private AuthenticationManagerIface authManager;
+// @Autowired
+ private JavaMailSender mailSender;
+// @Autowired
+ private VelocityEngine velocityEngine;
+
+ public void sendMemberInvitationNotification (String inviteeName,
+ String groupName, String inviter) {
+
+ MimeMessagePreparator preparator = new MimeMessagePreparator() {
+
+ public void prepare (MimeMessage mimeMessage) throws Exception {
+
+ User invitee = authManager.getUser(inviteeName);
+
+ MimeMessageHelper message = new MimeMessageHelper(mimeMessage);
+ message.setTo(new InternetAddress(invitee.getEmail()));
+ message.setFrom("noreply-korap-notification@ids-mannheim.de");
+ message.setSubject("Invitation to join group");
+ message.setText(prepareText(inviteeName, groupName, inviter),
+ true);
+ }
+
+ };
+ mailSender.send(preparator);
+ }
+
+ private String prepareText (String username, String groupName,
+ String inviter) {
+ Context context = new VelocityContext();
+ context.put("username", username);
+ context.put("groupName", groupName);
+ context.put("inviter", inviter);
+
+ StringWriter stringWriter = new StringWriter();
+ velocityEngine.mergeTemplate("invitationNotification.vm",
+ StandardCharsets.UTF_16.name(), context, stringWriter);
+ return stringWriter.toString();
+ }
+}
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
index 1dfd16f..e05053e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/UserGroupService.java
@@ -1,11 +1,8 @@
package de.ids_mannheim.korap.service;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
@@ -57,6 +54,8 @@
private AuthenticationManagerIface authManager;
@Autowired
private FullConfiguration config;
+ @Autowired
+ private MailService mailService;
private static List<Role> memberRoles;
@@ -176,7 +175,7 @@
// skip owner, already added while creating group.
continue;
}
- addGroupMember(memberId, userGroup, createdBy,
+ inviteGroupMember(memberId, userGroup, createdBy,
GroupMemberStatus.PENDING);
}
}
@@ -226,7 +225,7 @@
* @param status the status of the membership
* @throws KustvaktException
*/
- public void addGroupMember (String username, UserGroup userGroup,
+ public void inviteGroupMember (String username, UserGroup userGroup,
String createdBy, GroupMemberStatus status)
throws KustvaktException {
@@ -249,8 +248,12 @@
member.setRoles(memberRoles);
member.setStatus(status);
member.setUserId(username);
-
groupMemberDao.addMember(member);
+
+ if (config.isMailEnabled()) {
+ mailService.sendMemberInvitationNotification(username,
+ userGroup.getName(), createdBy);
+ }
}
private boolean memberExists (String username, int groupId,
@@ -277,7 +280,7 @@
return false;
}
- public void addUsersToGroup (UserGroupJson group, String username)
+ public void inviteGroupMembers (UserGroupJson group, String inviter)
throws KustvaktException {
int groupId = group.getId();
String[] members = group.getMembers();
@@ -285,16 +288,16 @@
ParameterChecker.checkObjectValue(members, "members");
UserGroup userGroup = retrieveUserGroupById(groupId);
- User user = authManager.getUser(username);
- if (isUserGroupAdmin(username, userGroup) || user.isSystemAdmin()) {
+ User user = authManager.getUser(inviter);
+ if (isUserGroupAdmin(inviter, userGroup) || user.isSystemAdmin()) {
for (String memberName : members) {
- addGroupMember(memberName, userGroup, username,
+ inviteGroupMember(memberName, userGroup, inviter,
GroupMemberStatus.PENDING);
}
}
else {
throw new KustvaktException(StatusCodes.AUTHORIZATION_FAILED,
- "Unauthorized operation for user: " + username, username);
+ "Unauthorized operation for user: " + inviter, inviter);
}
}
@@ -322,9 +325,9 @@
ParameterChecker.checkStringValue(username, "userId");
ParameterChecker.checkIntegerValue(groupId, "groupId");
-
+
UserGroup group = userGroupDao.retrieveGroupById(groupId);
-
+
UserGroupMember member =
groupMemberDao.retrieveMemberById(username, groupId);
GroupMemberStatus status = member.getStatus();
@@ -337,22 +340,21 @@
else if (member.getStatus().equals(GroupMemberStatus.ACTIVE)) {
throw new KustvaktException(StatusCodes.GROUP_MEMBER_EXISTS,
"Username " + username + " with status " + status
- + " exists in the user-group "
- + group.getName(),
+ + " exists in the user-group " + group.getName(),
username, status.name(), group.getName());
}
// status pending
else {
- jlog.debug("status: " +member.getStatusDate());
+ jlog.debug("status: " + member.getStatusDate());
ZonedDateTime expiration = member.getStatusDate().plusMinutes(30);
ZonedDateTime now = ZonedDateTime.now();
jlog.debug("expiration: " + expiration + ", now: " + now);
- if (expiration.isAfter(now)){
+ if (expiration.isAfter(now)) {
member.setStatus(GroupMemberStatus.ACTIVE);
groupMemberDao.updateMember(member);
}
- else{
+ else {
throw new KustvaktException(StatusCodes.INVITATION_EXPIRED);
}
}
@@ -405,9 +407,9 @@
*/
private void deleteMember (String username, int groupId, String deletedBy,
boolean isSoftDelete) throws KustvaktException {
-
+
UserGroup group = userGroupDao.retrieveGroupById(groupId);
-
+
UserGroupMember member =
groupMemberDao.retrieveMemberById(username, groupId);
GroupMemberStatus status = member.getStatus();
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
index b4e7fbc..4e0214b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/VirtualCorpusService.java
@@ -395,7 +395,7 @@
userGroupService.retrieveHiddenGroup(vcId);
// if (!userGroupService.isMember(username, userGroup)) {
try {
- userGroupService.addGroupMember(username, userGroup,
+ userGroupService.inviteGroupMember(username, userGroup,
"system", GroupMemberStatus.ACTIVE);
}
catch (KustvaktException e) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index eda4eeb..9e15d33 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -166,12 +166,12 @@
@POST
@Path("member/invite")
@Consumes(MediaType.APPLICATION_JSON)
- public Response addUserToGroup (@Context SecurityContext securityContext,
+ public Response inviteGroupMembers (@Context SecurityContext securityContext,
UserGroupJson group) {
TokenContext context =
(TokenContext) securityContext.getUserPrincipal();
try {
- service.addUsersToGroup(group, context.getUsername());
+ service.inviteGroupMembers(group, context.getUsername());
return Response.ok().build();
}
catch (KustvaktException e) {
diff --git a/full/src/main/resources/WEB-INF/web.xml b/full/src/main/resources/WEB-INF/web.xml
new file mode 100644
index 0000000..4c2a254
--- /dev/null
+++ b/full/src/main/resources/WEB-INF/web.xml
@@ -0,0 +1,5 @@
+<resource-ref>
+ <res-ref-name>mail/Session</res-ref-name>
+ <res-type>javax.mail.Session</res-type>
+ <res-auth>Container</res-auth>
+</resource-ref>
\ No newline at end of file
diff --git a/full/src/main/resources/kustvakt.conf b/full/src/main/resources/kustvakt.conf
index d8ff39d..2e29c02 100644
--- a/full/src/main/resources/kustvakt.conf
+++ b/full/src/main/resources/kustvakt.conf
@@ -10,6 +10,9 @@
ldap.config = file-path-to-ldap-config
# Kustvakt
+## mail settings
+mail.enabled = false
+
## default layers
default.layer.p = tt
default.layer.l = tt
diff --git a/full/src/main/resources/templates/invitationNotification.vm b/full/src/main/resources/templates/invitationNotification.vm
new file mode 100644
index 0000000..02cf5c6
--- /dev/null
+++ b/full/src/main/resources/templates/invitationNotification.vm
@@ -0,0 +1,13 @@
+<html>
+ <body>
+ <h3>Hi ${username}, you are invited to group {$group} by ${inviter}!</h3>
+ <p>
+ Login to KorAP to accept or reject the invitation.
+ <br />
+ The invitation is valid for 30 minutes.
+ </p>
+ <p>
+ Do not reply! This is an automated generated email.
+ </p>
+ </body>
+</html>
\ No newline at end of file