summaryrefslogblamecommitdiffstats
path: root/dozentenmodulserver/src/main/java/org/openslx/bwlp/sat/mail/MailGenerator.java
blob: 2ee6aa54f0f231e96d8b714b4f22cff312f6d8ff (plain) (tree)
1
2
3
4
5
6
7
8
                                  

                             
                               


                           
                        



                               
                                                             

                                                                
                                                       

                                                                  
                                                         
                                                              
                                                      
                                                            
                                           
                                      




                                                         
                                               


                                                        
                            
 
                                                                                   
 



                                                                                   




                                               
           

                                                                                                         

                                     
                                                         
                                                                              
 
                                                                                                          




                                                                           
                                                             

                                                                              
                                                 
                                                                               



                         



                                                                              




                                                       
           

                                                                                                           

                                     
                                                         
                                                                              
 
                                                                                                                






                                                                                        
                                                             
                                                                               




                                                                              

                                     
                                                         
                                                                              
                        
                                                                                                              




                                                                           
                                                             
                                                                               



                         
                                                                                                                                

                                     






                                                                                               









                                                                                                    




                                                                   
                               

                 
                                         
                                                                                                     
                        
                                                                                                    

                                            
                                                                                        
                                                                                                                    
                                                                       
                                                             
                         
                                                                   
                                                                   
                                                                                               
                        
                                                 
                                                                                                       
                         

                                

                                                                    
                                                                                                 


                 
                                                                                                               

                                     






                                                                                                               

                                                                                        

                                      
                
                                        
                                                                                                         
                                        
                                                                                                     


                               

                                                        



                                                                                
                                                                         
                                                     
                                                     

                                                                 

                                                                                   









                                                                                                  
                                                                   
                                         
                         
                                                                                                                                
                                                                          



                                                                         


                 
                                                                                          

                                     
                                                                      
                                                                                                   





                                                                         
                                                     
                                                                           


                 


















































                                                                                             




                                                                                                 




















                                                                                     
































































                                                                                                                            
 
package org.openslx.bwlp.sat.mail;

import java.sql.SQLException;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.openslx.bwlp.sat.database.mappers.DbConfiguration;
import org.openslx.bwlp.sat.database.mappers.DbImage;
import org.openslx.bwlp.sat.database.mappers.DbImagePermissions;
import org.openslx.bwlp.sat.database.mappers.DbLecture;
import org.openslx.bwlp.sat.database.mappers.DbLecturePermissions;
import org.openslx.bwlp.sat.database.mappers.DbUser;
import org.openslx.bwlp.sat.database.mappers.DbUser.User;
import org.openslx.bwlp.sat.database.models.LocalImageVersion;
import org.openslx.bwlp.sat.mail.MailQueue.MailConfig;
import org.openslx.bwlp.sat.mail.MailTemplatePlain.Template;
import org.openslx.bwlp.sat.util.Formatter;
import org.openslx.bwlp.sat.util.Util;
import org.openslx.bwlp.thrift.iface.ImageDetailsRead;
import org.openslx.bwlp.thrift.iface.ImagePermissions;
import org.openslx.bwlp.thrift.iface.ImageVersionDetails;
import org.openslx.bwlp.thrift.iface.LecturePermissions;
import org.openslx.bwlp.thrift.iface.LectureSummary;
import org.openslx.bwlp.thrift.iface.ShareMode;
import org.openslx.bwlp.thrift.iface.TNotFoundException;
import org.openslx.bwlp.thrift.iface.UserInfo;

public class MailGenerator {

	private static final Logger LOGGER = Logger.getLogger(MailGenerator.class);

	/**
	 * Called when an image has been updated, and linked lectures will be moved
	 * to the new image version.
	 * 
	 * @param lectures
	 *            List of affected lectures
	 * @param newVersion
	 *            version id of new image
	 * @throws SQLException
	 */
	public static void lectureAutoUpdate(List<LectureSummary> lectures, LocalImageVersion newVersion)
			throws SQLException {
		if (!hasMailConfig())
			return;
		for (LectureSummary lecture : lectures) {
			List<UserInfo> relevantUsers = getUserToMail(lecture);

			MailTemplate template = DbConfiguration.getMailTemplate(Template.LECTURE_UPDATED);
			Map<String, String> templateArgs = new HashMap<>();
			templateArgs.put("lecture", lecture.lectureName);

			String msg = template.format(templateArgs);

			for (UserInfo user : relevantUsers) {
				/* Don't notice about changes by user */
				if (newVersion.uploaderId.equals(user.userId))
					continue;
				MailQueue.queue(new Mail(user, wordWrap(msg)));
			}
		}
	}

	/**
	 * Called when a lecture is downgraded, or a lecture is updated and it
	 * doesn't have auto-updates enabled.
	 * 
	 * @param lectures
	 *            list of affected lectures
	 * @param newVersion
	 *            the new version being switched to
	 * @throws SQLException
	 */
	public static void lectureForcedUpdate(List<LectureSummary> lectures, LocalImageVersion newVersion)
			throws SQLException {
		if (!hasMailConfig())
			return;
		for (LectureSummary lecture : lectures) {
			List<UserInfo> relevantUsers = getUserToMail(lecture);

			MailTemplate template = DbConfiguration.getMailTemplate(Template.LECTURE_FORCED_UPDATE);
			Map<String, String> templateArgs = new HashMap<>();
			templateArgs.put("lecture", lecture.lectureName);
			templateArgs.put("date", Formatter.date(newVersion.createTime));

			String msg = template.format(templateArgs);

			
			for (UserInfo user : relevantUsers) {
				MailQueue.queue(new Mail(user, wordWrap(msg)));
			}
		}
	}

	public static void lectureDeactivated(List<LectureSummary> lectures) {
		if (!hasMailConfig())
			return;
		for (LectureSummary lecture : lectures) {
			List<UserInfo> relevantUsers = getUserToMail(lecture);
			
			MailTemplate template = DbConfiguration.getMailTemplate(Template.LECTURE_DEACTIVATED);
			Map<String, String> templateArgs = new HashMap<>();
			templateArgs.put("lecture", lecture.lectureName);
			
			String msg = template.format(templateArgs);
			
			for (UserInfo user : relevantUsers) {
				MailQueue.queue(new Mail(user, wordWrap(msg)));
			}
		}
	}

	public static void sendImageVersionDeleted(String imageBaseId, LocalImageVersion oldLocal, LocalImageVersion newLocal) {
		if (!hasMailConfig())
			return;
		ImageDetailsRead image;
		try {
			image = DbImage.getImageDetails(null, imageBaseId);
		} catch (TNotFoundException | SQLException e) {
			LOGGER.warn("Version Deleted for image=" + imageBaseId + " failed", e);
			return;
		}
		ImageVersionDetails oldVersion = null;
		ImageVersionDetails newVersion = null;
		for (ImageVersionDetails version : image.versions) {
			if (oldLocal != null && version.versionId.equals(oldLocal.imageVersionId)) {
				oldVersion = version;
			}
			if (newLocal != null && version.versionId.equals(newLocal.imageVersionId)) {
				newVersion = version;
			}
		}
		
		MailTemplate template;
		Map<String, String> templateArgs = new HashMap<>();
				
		if (oldVersion == newVersion) {
			return;
		}
		
		if (newVersion == null) {
			template = DbConfiguration.getMailTemplate(Template.VM_DELETED_LAST_VERSION);
		} else {
			template = DbConfiguration.getMailTemplate(Template.VM_DELETED_OLD_VERSION);
			String uploaderName;
			try {
				User uploader = DbUser.getCached(newVersion.uploaderId);
				uploaderName = Formatter.userFullName(uploader.ui) + " <" + uploader.ui.eMail + ">";
			} catch (TNotFoundException | SQLException e) {
				uploaderName = "(unbekannt)";
			}
			templateArgs.put("image", image.imageName);
			templateArgs.put("uploader", uploaderName);
			templateArgs.put("new_created", Formatter.date(newVersion.createTime));
			
			if (oldVersion != null) {
				templateArgs.put("old_created", Formatter.date(oldVersion.createTime));
			}
		}		
		
		List<UserInfo> relevantUsers = getUserToMail(image);
		for (UserInfo user : relevantUsers) {
			MailQueue.queue(new Mail(user, wordWrap(template.format(templateArgs))));
		}
	}

	public static void sendImageDeletionReminder(LocalImageVersion version, int days, boolean mailForced) {
		if (!hasMailConfig())
			return;
		ImageDetailsRead image;
		try {
			image = DbImage.getImageDetails(null, version.imageBaseId);
		} catch (TNotFoundException | SQLException e) {
			LOGGER.warn("Could not get image details for image version " + version.imageVersionId);
			return;
		}
		boolean isCurrentlyLatest = image.latestVersionId == null
				|| image.latestVersionId.equals(version.imageVersionId);
			
		MailTemplate template;
		
		if (isCurrentlyLatest) {
			template = DbConfiguration.getMailTemplate(Template.VM_CURRENT_VERSION_EXPIRING);
		} else if (mailForced) {
			template = DbConfiguration.getMailTemplate(Template.VM_OLD_VERSION_EXPIRING);
		} else {
			return;
		}
		List<UserInfo> relevantUsers;
		// Mail users responsible for this image
		Map<String, String> templateArgs = new HashMap<>();
		templateArgs.put("image", image.imageName);
		templateArgs.put("remaining_days", String.valueOf(days));
		templateArgs.put("created", Formatter.date(version.createTime));
		String message = wordWrap(template.format(templateArgs));
		relevantUsers = getUserToMail(image);
		for (UserInfo user : relevantUsers) {
			MailQueue.queue(new Mail(user, message));
		}
		// Mail users using this image for a lecture, but only if the image
		// expires before the lecture ends
		// And the image to delete is currently the newest image
		if (!isCurrentlyLatest)
			return;
		List<LectureSummary> lectures;
		try {
			lectures = DbLecture.getLecturesUsingImageVersion(version.imageVersionId);
		} catch (SQLException e) {
			lectures = new ArrayList<>(0);
		}
		for (LectureSummary lecture : lectures) {
			if (lecture.endTime < version.expireTime) {
				continue;
			}
			template = DbConfiguration.getMailTemplate(Template.LECTURE_LINKED_VM_EXPIRING);			
			message = wordWrap(template.format(templateArgs));
			relevantUsers = getUserToMail(lecture);
			for (UserInfo user : relevantUsers) {
				MailQueue.queue(new Mail(user, message));
			}
		}
	}

	public static void sendLectureExpiringReminder(LectureSummary lecture, int days) {
		if (!hasMailConfig())
			return;
		List<UserInfo> relevantUsers = getUserToMail(lecture);
		MailTemplate template = DbConfiguration.getMailTemplate(Template.LECTURE_EXPIRING);
		Map<String, String> templateArgs = new HashMap<>();
		templateArgs.put("lecture", lecture.lectureName);
		templateArgs.put("remaining_days", String.valueOf(days));
		
		String message = template.format(templateArgs);
		
		for (UserInfo user : relevantUsers) {
			MailQueue.queue(new Mail(user, wordWrap(message)));
		}
	}

	public static boolean isValidMailConfig(MailConfig conf) {
		return conf != null && conf.port != 0 && !Util.isEmptyString(conf.host)
				&& !Util.isEmptyString(conf.senderAddress);
	}

	private static boolean hasMailConfig() {
		MailConfig conf;
		try {
			conf = DbConfiguration.getMailConfig();
		} catch (SQLException e) {
			return false;
		}
		return isValidMailConfig(conf);
	}

	private static List<UserInfo> getUserToMail(LectureSummary lecture) {
		Map<String, LecturePermissions> users;
		try {
			users = DbLecturePermissions.getForLecture(lecture.lectureId, false);
		} catch (SQLException e) {
			users = new HashMap<>();
		}
		users.put(lecture.ownerId, new LecturePermissions(true, true));
		List<UserInfo> list = new ArrayList<>(users.size());
		for (Entry<String, LecturePermissions> entry : users.entrySet()) {
			LecturePermissions perms = entry.getValue();
			if (!perms.admin && !perms.edit)
				continue;
			User user;
			try {
				user = DbUser.getCached(entry.getKey());
			} catch (TNotFoundException e) {
				LOGGER.warn("UserID " + entry.getKey() + " unknown");
				continue;
			} catch (SQLException e) {
				continue; // Logging happened in DbUser
			}
			if (user.local.emailNotifications) {
				list.add(user.ui);
			}
		}
		return list;
	}

	private static List<UserInfo> getUserToMail(ImageDetailsRead image) {
		Map<String, ImagePermissions> users;
		try {
			users = DbImagePermissions.getForImageBase(image.imageBaseId, false);
		} catch (SQLException e) {
			users = new HashMap<>();
		}
		// For images downloaded from master server, don't email the owner, as the owner
		// is from some other organization (usually)
		if (image.shareMode == ShareMode.LOCAL || image.shareMode == ShareMode.PUBLISH) {
			users.put(image.ownerId, new ImagePermissions(true, true, true, true));
		}
		List<UserInfo> list = new ArrayList<>(users.size());
		for (Entry<String, ImagePermissions> entry : users.entrySet()) {
			ImagePermissions perms = entry.getValue();
			if (!perms.admin && !perms.edit)
				continue;
			User user;
			try {
				user = DbUser.getCached(entry.getKey());
			} catch (TNotFoundException e) {
				LOGGER.warn("UserID " + entry.getKey() + " unknown");
				continue;
			} catch (SQLException e) {
				continue; // Logging happened in DbUser
			}
			if (user.local.emailNotifications) {
				list.add(user.ui);
			}
		}
		return list;
	}

	private static String wordWrap(String input) {
		return wordWrap(input, 76, "\n  ", Locale.GERMAN);
	}

	private static String wordWrap(String input, int width, String nlString, Locale locale) {
		if (input == null) {
			return "";
		} else if (width < 5) {
			return input;
		} else if (width >= input.length()) {
			return input;
		}

		StringBuilder buf = new StringBuilder(input);
		boolean endOfLine = false;
		int lineStart = 0;

		for (int i = 0; i < buf.length(); i++) {
			if (buf.charAt(i) == '\n') {
				lineStart = i + 1;
				endOfLine = true;
			}

			// handle splitting at width character
			if (i > lineStart + width - 1) {
				if (endOfLine) {
					buf.insert(i, nlString);
					lineStart = i + nlString.length();
					endOfLine = false;
				} else {
					int limit = i - lineStart - 1;
					BreakIterator breaks = BreakIterator.getLineInstance(locale);
					breaks.setText(buf.substring(lineStart, i));
					int end = breaks.last();

					// if the last character in the search string isn't a space,
					// we can't split on it (looks bad). Search for a previous
					// break character
					if (end == limit + 1) {
						if (!Character.isWhitespace(buf.charAt(lineStart + end))) {
							end = breaks.preceding(end - 1);
						}
					}

					// if the last character is a space, replace it with a \n
					if (end != BreakIterator.DONE && end == limit + 1) {
						buf.replace(lineStart + end, lineStart + end + 1, nlString.substring(0, 1));
						buf.insert(lineStart + end + 1, nlString.substring(1));
						lineStart = lineStart + end + nlString.length() - 1;
					}
					// otherwise, just insert a \n
					else if (end != BreakIterator.DONE && end != 0) {
						buf.insert(lineStart + end, nlString);
						lineStart = lineStart + end + nlString.length();
					} else {
						buf.insert(i, nlString);
						lineStart = i + nlString.length();
					}
				}
			}
		}

		return buf.toString();
	}

}