package de.rwth.idsg.steve.repository.impl; import com.google.common.base.Joiner; import com.google.common.base.Splitter; import de.rwth.idsg.steve.NotificationFeature; import de.rwth.idsg.steve.SteveException; import de.rwth.idsg.steve.repository.SettingsRepository; import de.rwth.idsg.steve.repository.dto.MailSettings; import de.rwth.idsg.steve.web.dto.SettingsForm; import jooq.steve.db.tables.records.SettingsRecord; import org.jooq.DSLContext; import org.jooq.exception.DataAccessException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static jooq.steve.db.tables.Settings.SETTINGS; /** * @author Sevket Goekay <goekay@dbis.rwth-aachen.de> * @since 06.11.2015 */ @Repository public class SettingsRepositoryImpl implements SettingsRepository { // Totally unnecessary to specify charset here. We just do it to make findbugs plugin happy. // private static final String APP_ID = new String( Base64.getEncoder().encode("SteckdosenVerwaltung".getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8 ); private static final Splitter SPLITTER = Splitter.on(",").trimResults().omitEmptyStrings(); private static final Joiner JOINER = Joiner.on(",").skipNulls(); @Autowired private DSLContext ctx; @Override public SettingsForm getForm() { SettingsRecord r = getInternal(); List<String> eMails = split(r.getMailRecipients()); List<NotificationFeature> features = splitFeatures(r.getNotificationFeatures()); return SettingsForm.builder() .heartbeat(toMin(r.getHeartbeatIntervalInSeconds())) .expiration(r.getHoursToExpire()) .enabled(r.getMailEnabled()) .host(r.getMailHost()) .username(r.getMailUsername()) .password(r.getMailPassword()) .from(r.getMailFrom()) .protocol(r.getMailProtocol()) .port(r.getMailPort()) .recipients(eMails) .enabledFeatures(features) .build(); } @Override public MailSettings getMailSettings() { SettingsRecord r = getInternal(); List<String> eMails = split(r.getMailRecipients()); List<NotificationFeature> features = splitFeatures(r.getNotificationFeatures()); return MailSettings.builder() .enabled(r.getMailEnabled()) .host(r.getMailHost()) .username(r.getMailUsername()) .password(r.getMailPassword()) .from(r.getMailFrom()) .protocol(r.getMailProtocol()) .port(r.getMailPort()) .recipients(eMails) .enabledFeatures(features) .build(); } @Override public int getHeartbeatIntervalInSeconds() { return getInternal().getHeartbeatIntervalInSeconds(); } @Override public int getHoursToExpire() { return getInternal().getHoursToExpire(); } @Override public void update(SettingsForm form) { String eMails = join(form.getRecipients()); String features = join(form.getEnabledFeatures()); try { ctx.update(SETTINGS) .set(SETTINGS.HEARTBEAT_INTERVAL_IN_SECONDS, toSec(form.getHeartbeat())) .set(SETTINGS.HOURS_TO_EXPIRE, form.getExpiration()) .set(SETTINGS.MAIL_ENABLED, form.getEnabled()) .set(SETTINGS.MAIL_HOST, form.getHost()) .set(SETTINGS.MAIL_USERNAME, form.getUsername()) .set(SETTINGS.MAIL_PASSWORD, form.getPassword()) .set(SETTINGS.MAIL_FROM, form.getFrom()) .set(SETTINGS.MAIL_PROTOCOL, form.getProtocol()) .set(SETTINGS.MAIL_PORT, form.getPort()) .set(SETTINGS.MAIL_RECIPIENTS, eMails) .set(SETTINGS.NOTIFICATION_FEATURES, features) .where(SETTINGS.APP_ID.eq(APP_ID)) .execute(); } catch (DataAccessException e) { throw new SteveException("FAILED to save the settings", e); } } private SettingsRecord getInternal() { return ctx.selectFrom(SETTINGS) .where(SETTINGS.APP_ID.eq(APP_ID)) .fetchOne(); } private static int toMin(int seconds) { return (int) TimeUnit.SECONDS.toMinutes(seconds); } private static int toSec(int minutes) { return (int) TimeUnit.MINUTES.toSeconds(minutes); } @Nullable private String join(Collection<?> col) { if (col == null || col.isEmpty()) { return null; } else { // Use HashSet to trim duplicates before inserting into DB return JOINER.join(new HashSet<>(col)); } } private List<String> split(String str) { if (str == null || str.isEmpty()) { return Collections.emptyList(); } else { return SPLITTER.splitToList(str); } } private List<NotificationFeature> splitFeatures(String str) { return split(str).stream() .map(NotificationFeature::fromName) .collect(Collectors.toList()); } }