/* * Copyright (C) 2008-2017, Juick * * 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.controllers; import com.juick.server.component.UserUpdatedEvent; import com.juick.server.helpers.NotifyOpts; import com.juick.server.helpers.UserInfo; import com.juick.server.util.*; import com.juick.service.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import javax.inject.Inject; 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.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * * @author Ugnich Anton */ @Controller public class Settings { private static final Logger logger = LoggerFactory.getLogger(Settings.class); @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}") private String imgDir; @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}") private String tmpDir; @Inject private TagService tagService; @Inject private UserService userService; @Inject private CrosspostService crosspostService; @Inject private SubscriptionService subscriptionService; @Inject private EmailService emailService; @Inject private TelegramService telegramService; @Inject private ApplicationEventPublisher applicationEventPublisher; @GetMapping("/settings") protected String doGet(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws IOException { com.juick.User visitor = UserUtils.getCurrentUser(); 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"; } model.addAttribute("title", "Настройки"); model.addAttribute("visitor", visitor); model.addAttribute("tags", tagService.getPopularTags()); model.addAttribute("auths", userService.getAuthCodes(visitor)); model.addAttribute("eopts", userService.getEmailOpts(visitor)); model.addAttribute("ehash", userService.getEmailHash(visitor)); model.addAttribute("emails", userService.getEmails(visitor)); model.addAttribute("jids", userService.getAllJIDs(visitor)); List hours = IntStream.rangeClosed(0, 23).boxed() .map(i -> StringUtils.leftPad(String.format("%d", i), 2, "0")).collect(Collectors.toList()); model.addAttribute("hours", hours); model.addAttribute("fbstatus", crosspostService.getFbCrossPostStatus(visitor.getUid())); model.addAttribute("twitter_name", crosspostService.getTwitterName(visitor.getUid())); model.addAttribute("telegram_name", crosspostService.getTelegramName(visitor.getUid())); model.addAttribute("notify_options", subscriptionService.getNotifyOptions(visitor)); model.addAttribute("userinfo", userService.getUserInfo(visitor)); if (page.equals("auth-email")) { if (emailService.verifyAddressByCode(visitor.getUid(), request.getParameter("code"))) { ; model.addAttribute("result", "OK!"); } else { model.addAttribute("result", "Sorry, code unknown."); } } return String.format("views/settings_%s", page); } @PostMapping("/settings") protected String doPost(HttpServletRequest request, HttpServletResponse response, @RequestParam(required = false) MultipartFile avatar, ModelMap model) throws IOException, ServletException { com.juick.User visitor = UserUtils.getCurrentUser(); if (visitor.getUid() == 0) { throw new HttpBadRequestException(); } 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)) { throw new HttpBadRequestException(); } String result = StringUtils.EMPTY; switch (page) { case "password": if (userService.updatePassword(visitor, request.getParameter("password"))) { result = "

Password has been changed.

"; String hash = userService.getHashByUID(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 (subscriptionService.setNotifyOptions(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 = HttpUtils.receiveMultiPartFile(avatar, tmpDir); if (StringUtils.isNotEmpty(avatarTmpPath)) { ImageUtils.saveAvatar(avatarTmpPath, visitor.getUid(), tmpDir, imgDir); } if (userService.updateUserInfo(visitor, info)) { applicationEventPublisher.publishEvent(new UserUpdatedEvent(this, visitor)); result = String.format("

Your info is updated.

Back to blog.

", visitor.getName()); } break; case "jid-del": // FIXME: stop using ugnich-csv in parameters String[] params = request.getParameter("delete").split(";", 2); boolean res = false; if (params[0].equals("xmpp")) { res = userService.deleteJID(visitor.getUid(), params[1]); } else if (params[0].equals("xmpp-unauth")) { res = userService.unauthJID(visitor.getUid(), params[1]); } if (res) { result = "

Deleted. Back.

"; } else { result = "

Error

"; } break; case "email-add": if (!emailService.verifyAddressByCode(visitor.getUid(), request.getParameter("account"))) { String authCode = HashUtils.generateHash(8); if (emailService.addVerificationCode(visitor.getUid(), request.getParameter("account"), authCode)) { 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); throw new HttpBadRequestException(); } } } break; case "email-del": if (emailService.deleteEmail(visitor.getUid(), request.getParameter("account"))) { result = "

Deleted. Back.

"; } else { result = "

An error occured while deleting.

"; } break; case "email-subscr": if (emailService.setNotificationsEmail(visitor.getUid(), request.getParameter("account"))) { result = String.format("

Saved! Will send notifications to %s." + "

Back

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

Disabled.

Back

"; } break; case "twitter-del": crosspostService.deleteTwitterToken(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": telegramService.deleteTelegramUser(visitor.getUid()); telegramService.getTelegramIdentifiers(Collections.singletonList(visitor)).forEach(t -> { telegramService.deleteChat(t); }); result = "

Back

"; break; case "facebook-disable": crosspostService.disableFBCrosspost(visitor.getUid()); result = "

Back

"; break; case "facebook-enable": crosspostService.enableFBCrosspost(visitor.getUid()); result = "

Back

"; break; case "vk-del": crosspostService.deleteVKUser(visitor.getUid()); result = "

Back

"; break; default: throw new HttpBadRequestException(); } model.addAttribute("title", "Настройки"); model.addAttribute("visitor", visitor); model.addAttribute("result", result); return "views/settings_result"; } }