/*
* Copyright (C) 2008-2023, 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.model.User;
import com.juick.util.HttpBadRequestException;
import com.juick.util.HttpForbiddenException;
import com.juick.util.UsernameTakenException;
import com.juick.www.WebApp;
import com.juick.service.EmailService;
import com.juick.service.UserService;
import com.juick.service.security.entities.JuickUser;
import io.swagger.v3.oas.annotations.Parameter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
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 jakarta.inject.Inject;
/**
*
* @author Ugnich Anton
*/
@Controller
public class SignUp {
@Inject
private UserService userService;
@Inject
private EmailService emailService;
@Inject
private WebApp webApp;
@Inject
private RememberMeServices rememberMeServices;
@GetMapping("/signup")
protected String doGet(
@Parameter(hidden = true) User visitor,
@RequestParam String type, @RequestParam String hash, ModelMap model) {
if (hash.length() > 36 || !type.matches("^[a-zA-Z0-9\\-]+$")
|| !hash.matches("^[a-zA-Z0-9\\-]+$")) {
throw new HttpBadRequestException();
}
String account = null;
switch (type) {
case "fb":
account = userService.getFacebookNameByHash(hash);
break;
case "vk":
account = userService.getVKNameByHash(hash);
break;
case "xmpp":
account = userService.getJIDByHash(hash);
break;
case "durov":
account = userService.getTelegramNameByHash(hash);
break;
case "email":
account = emailService.getEmailByAuthCode(hash);
}
if (account == null) {
throw new HttpBadRequestException();
}
model.addAttribute("title", "Новый пользователь");
visitor.setAvatar(webApp.getAvatarWebPath(visitor));
model.addAttribute("visitor", visitor);
model.addAttribute("account", account);
model.addAttribute("type", type);
model.addAttribute("hash", hash);
model.addAttribute("headers", "");
return "views/signup";
}
@PostMapping("/signup")
protected String doPost(
HttpServletRequest request,
HttpServletResponse response,
@Parameter(hidden = true) User visitor,
@RequestParam String type,
@RequestParam String hash,
@RequestParam String action,
@RequestParam(required = false) String username,
@RequestParam(required = false) String password,
ModelMap modelMap) {
User current;
if (hash.length() > 36 || !type.matches("^[a-zA-Z0-9\\-]+$") || !hash.matches("^[a-zA-Z0-9\\-]+$")) {
modelMap.addAttribute("result", "Invalid request");
modelMap.addAttribute("visitor", visitor);
return "views/signup_result";
}
if (action.charAt(0) == 'l') {
if (visitor.isAnonymous()) {
if (username.length() > 32) {
modelMap.addAttribute("result", "Invalid request");
modelMap.addAttribute("visitor", visitor);
return "views/signup_result";
}
current = userService.checkPassword(username, password).orElseThrow(HttpForbiddenException::new);
} else {
current = visitor;
}
if (current.getUid() <= 0) {
modelMap.addAttribute("result", "Invalid request");
modelMap.addAttribute("visitor", visitor);
return "views/signup_result";
}
if (!(type.charAt(0) == 'f' && userService.setFacebookUser(hash, current.getUid()))
&& !(type.charAt(0) == 'v' && userService.setVKUser(hash, current.getUid()))
&& !(type.charAt(0) == 'd' && userService.setTelegramUser(hash, current.getUid()))
&& !(type.charAt(0) == 'x' && userService.getAllJIDs(visitor).size() > 0
&& userService.setJIDUser(hash, current.getUid()))) {
if (type.equals("email")) {
String email = emailService.getEmailByAuthCode(hash);
emailService.addEmail(current.getUid(), email);
emailService.deleteAuthCode(hash);
} else {
if (type.equals("xmpp")) {
modelMap.addAttribute("result", "XMPP support is disabled for new users");
} else {
modelMap.addAttribute("result", "Invalid request");
}
modelMap.addAttribute("visitor", visitor);
return "views/signup_result";
}
}
} else { // Create new account
if (username.length() < 2 || username.length() > 16 || !username.matches("^[a-zA-Z0-9\\-]+$") || password.length() < 6 || password.length() > 32) {
modelMap.addAttribute("visitor", visitor);
modelMap.addAttribute("result", "Bad username or password");
return "views/signup_result";
}
try {
current = userService.createUser(username, password).orElseThrow(HttpBadRequestException::new);
} catch(UsernameTakenException e) {
modelMap.addAttribute("visitor", visitor);
modelMap.addAttribute("result", e.getMessage());
return "views/signup_result";
}
if (!(type.charAt(0) == 'f' && userService.setFacebookUser(hash, current.getUid()))
&& !(type.charAt(0) == 'v' && userService.setVKUser(hash, current.getUid()))
&& !(type.charAt(0) == 'd' && userService.setTelegramUser(hash, current.getUid()))) {
if (type.equals("email")) {
String email = emailService.getEmailByAuthCode(hash);
emailService.addEmail(current.getUid(), email);
emailService.deleteAuthCode(hash);
} else {
if (type.equals("xmpp")) {
modelMap.addAttribute("result", "XMPP support is disabled for new users");
} else {
modelMap.addAttribute("result", "Invalid request");
}
modelMap.addAttribute("visitor", visitor);
return "views/signup_result";
}
}
}
if (visitor.isAnonymous()) {
var authentication = new RememberMeAuthenticationToken(
((AbstractRememberMeServices) rememberMeServices).getKey(),
new JuickUser(current), JuickUser.USER_AUTHORITY);
SecurityContextHolder.getContext().setAuthentication(authentication);
rememberMeServices.loginSuccess(request, response, authentication);
}
return "redirect:/";
}
}