/* * Juick * Copyright (C) 2008-2013, Ugnich Anton * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package com.juick.www; import com.juick.server.CrosspostQueries; import com.juick.server.SubscriptionsQueries; import com.juick.server.TagQueries; import com.juick.server.UserQueries; import com.juick.server.helpers.NotifyOpts; import com.juick.server.helpers.UserInfo; import com.juick.util.UserUtils; import com.mitchellbosecke.pebble.error.PebbleException; import com.mitchellbosecke.pebble.template.PebbleTemplate; import net.coobird.thumbnailator.Thumbnails; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * * @author Ugnich Anton */ public class Settings { private static final Logger logger = LoggerFactory.getLogger(Settings.class); private final String imgPath; public Settings(String avatarsPath) { this.imgPath = avatarsPath; } protected void doGet(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, PebbleException { com.juick.User visitor = Utils.getVisitorUser(sql, request, response); if (visitor.getUid() == 0) { response.sendRedirect("/login"); } List pages = Arrays.asList("main", "password", "about", "auth-email", "privacy"); String page = request.getParameter("page"); if (StringUtils.isEmpty(page) || !pages.contains(page)) { page = "main"; } response.setContentType("text/html; charset=UTF-8"); try (PrintWriter out = response.getWriter()) { PebbleTemplate template = Utils.getEngine().getTemplate(String.format("views/settings_%s.html", page)); Map context = new HashMap<>(); context.put("title", "Настройки"); context.put("visitor", visitor); context.put("tags", TagQueries.getPopularTags(sql)); context.put("auths", UserQueries.getAuthCodes(sql, visitor)); context.put("eopts", UserQueries.getEmailOpts(sql, visitor)); context.put("ehash", UserQueries.getEmailHash(sql, visitor)); context.put("emails", UserQueries.getEmails(sql, visitor)); context.put("jids", UserQueries.getAllJIDs(sql, visitor)); List hours = IntStream.rangeClosed(0, 23).boxed() .map(i -> StringUtils.leftPad(String.format("%d", i), 2, "0")).collect(Collectors.toList()); context.put("hours", hours); context.put("fbstatus", CrosspostQueries.isFBCrossPostEnabled(sql, visitor.getUid())); context.put("twitter_name", CrosspostQueries.getTwitterName(sql, visitor.getUid())); context.put("telegram_name", CrosspostQueries.getTelegramName(sql, visitor.getUid())); context.put("notify_options", SubscriptionsQueries.getNotifyOptions(sql, visitor)); context.put("userinfo", UserQueries.getUserInfo(sql, visitor)); if (page.equals("auth-email")) { try { String account = sql.queryForObject("SELECT account FROM auth WHERE user_id=? AND protocol='email' AND authcode=?", String.class, visitor.getUid(), request.getParameter("code")); sql.update("INSERT INTO emails(user_id,email) VALUES (?,?)", visitor.getUid(), account); sql.update("DELETE FROM auth WHERE user_id=? AND authcode=?", visitor.getUid(), request.getParameter("code")); context.put("result", "OK!"); } catch (EmptyResultDataAccessException e) { context.put("result", "Sorry, code unknown."); } } template.evaluate(out, context); } } protected void doPost(JdbcTemplate sql, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, PebbleException { com.juick.User visitor = Utils.getVisitorUser(sql, request, response); if (visitor.getUid() == 0) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } List pages = Arrays.asList("main", "password", "about", "email", "email-add", "email-del", "email-subscr", "auth-email", "privacy", "jid-del", "twitter-del", "telegram-del", "facebook-disable", "facebook-enable", "vk-del"); String page = request.getParameter("page"); if (StringUtils.isEmpty(page) || !pages.contains(page)) { response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } String result = StringUtils.EMPTY; switch (page) { case "password": if (UserQueries.updatePassword(sql, visitor, request.getParameter("password"))) { result = "

Password has been changed.

"; String hash = com.juick.server.UserQueries.getHashByUID(sql, visitor.getUid()); Cookie c = new Cookie("hash", hash); c.setMaxAge(365 * 24 * 60 * 60); response.addCookie(c); } break; case "main": NotifyOpts opts = new NotifyOpts(); opts.setRepliesEnabled(StringUtils.isNotEmpty(request.getParameter("jnotify"))); opts.setSubscriptionsEnabled(StringUtils.isNotEmpty(request.getParameter("subscr_notify"))); opts.setRecommendationsEnabled(StringUtils.isNotEmpty(request.getParameter("recomm"))); if (SubscriptionsQueries.setNotifyOptions(sql, visitor, opts)) { result = "

Notification options has been updated

"; } break; case "about": UserInfo info = new UserInfo(); info.setFullName(request.getParameter("fullname")); info.setCountry(request.getParameter("country")); info.setUrl(request.getParameter("url")); info.setDescription(request.getParameter("descr")); String avatarTmpPath = Utils.receiveMultiPartFile(request.getPart("avatar")); if (StringUtils.isNotEmpty(avatarTmpPath)) { String originalExtension = FilenameUtils.getExtension(avatarTmpPath); String originalName = String.format("%s.%s", visitor.getUid(), originalExtension); String targetName = String.format("%s.png", visitor.getUid()); Path ao = Paths.get(imgPath, "ao", originalName); Path a = Paths.get(imgPath, "a", targetName); Path as = Paths.get(imgPath, "as", targetName); Files.move(Paths.get(Utils.getTmpDir(), avatarTmpPath), ao, StandardCopyOption.REPLACE_EXISTING); Thumbnails.of(ao.toFile()).size(96, 96).toFile(a.toFile()); Thumbnails.of(ao.toFile()).size(32, 32).toFile(as.toFile()); } if (UserQueries.updateUserInfo(sql, visitor, info)) { result = String.format("

Your info is updated.

Back to blog.

", visitor.getName()); } break; case "jid-del": String[] params = request.getParameter("delete").split(";", 2); int res = -1; if (params[0].equals("xmpp")) { res = sql.update("DELETE FROM jids WHERE user_id=? AND jid=?", visitor.getUid(), params[1]); } else if (params[0].equals("xmpp-unauth")) { res = sql.update("DELETE FROM auth WHERE user_id=? AND protocol='xmpp' AND account=?", visitor.getUid(), params[1]); } if (res == 1) { result = "

Deleted. Back.

"; } else { result = "

Error

"; } break; case "email": String newHash = UserQueries.updateSecretEmail(sql, visitor); if (StringUtils.isNotEmpty(newHash)) { result = String.format("

New secret email: %s@mail.juick.com

" + "

Back.

", newHash); } else { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } break; case "email-add": try { sql.queryForObject("SELECT authcode FROM auth WHERE user_id=? AND protocol='email' " + "AND account=?", String.class, visitor.getUid(), request.getParameter("account")); } catch (EmptyResultDataAccessException e) { String authCode = UserUtils.generateHash(8); if (sql.update("INSERT INTO auth(user_id,protocol,account,authcode) VALUES (?,'email',?,?)", visitor.getUid(), request.getParameter("account"), authCode) > 0) { Session session = Session.getDefaultInstance(System.getProperties()); try { MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress("noreply@mail.juick.com")); message.addRecipient(Message.RecipientType.TO, new InternetAddress(request.getParameter("account"))); message.setSubject("Juick authorization link"); message.setText(String.format("Follow link to attach this email to Juick account:\n" + "http://juick.com/settings?page=auth-email&code=%s\n\n" + "If you don't know, what this mean - just ignore this mail.\n", authCode)); Transport.send(message); result = "

Authorization link has been sent to your email. Follow it to proceed.

" + "

Back

"; } catch (MessagingException ex) { logger.error("mail exception", ex); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } } } break; case "email-del": if (sql.update("DELETE FROM emails WHERE user_id=? AND email=?", visitor.getUid(), request.getParameter("account")) > 0) { result = "

Deleted. Back.

"; } else { result = "

An error occured while deleting.

"; } break; case "email-subscr": sql.update("UPDATE emails SET subscr_hour=NULL WHERE user_id=?", visitor.getUid()); String email = request.getParameter("account"); if (StringUtils.isNotEmpty(email)) { sql.update("UPDATE emails SET subscr_hour=? WHERE user_id=? AND email=?", request.getParameter("time"), visitor.getUid(), email); result = String.format("

Saved! Will send to %s at %s:00 GMT." + "

Back

", email, request.getParameter("time")); } else { result = "

Disabled.

Back

"; } break; case "twitter-del": sql.update("DELETE FROM twitter WHERE user_id=?", visitor.getUid()); sql.update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=1741", visitor.getUid()); for (Cookie cookie : request.getCookies()) { if (cookie.getName().equals("request_token")) { cookie.setMaxAge(0); response.addCookie(cookie); } if (cookie.getName().equals("request_token_secret")) { cookie.setMaxAge(0); response.addCookie(cookie); } } result = "

Back

"; break; case "telegram-del": sql.update("DELETE FROM telegram WHERE user_id=?", visitor.getUid()); result = "

Back

"; break; case "facebook-disable": sql.update("UPDATE facebook SET crosspost=0 WHERE user_id=?", visitor.getUid()); sql.update("DELETE FROM subscr_users WHERE user_id=? AND suser_id=5863", visitor.getUid()); result = "

Back

"; break; case "facebook-enable": sql.update("UPDATE facebook SET crosspost=1 WHERE user_id=?", visitor.getUid()); sql.update("INSERT INTO subscr_users(user_id,suser_id,jid,active) VALUES (?,5863,'juick@facebook.juick.com',1)", visitor.getUid()); result = "

Back

"; break; case "vk-del": sql.update("DELETE FROM vk WHERE user_id=?", visitor.getUid()); result = "

Back

"; break; default: response.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } response.setContentType("text/html; charset=UTF-8"); try (PrintWriter out = response.getWriter()) { PebbleTemplate template = Utils.getEngine().getTemplate("views/settings_result.html"); Map context = new HashMap<>(); context.put("title", "Настройки"); context.put("visitor", visitor); context.put("result", result); template.evaluate(out, context); } } }