/*
* This file is part of anycook. The new internet cookbook
* Copyright (C) 2014 Jan Graßegger
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see [http://www.gnu.org/licenses/].
*/
package de.anycook.api;
import de.anycook.api.util.MediaType;
import de.anycook.api.views.PrivateView;
import de.anycook.db.mysql.DBUser;
import de.anycook.session.LoginAttempt;
import de.anycook.session.Session;
import de.anycook.sitemap.SiteMapGenerator;
import de.anycook.user.User;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
@Path("session")
public class SessionApi {
private final Logger logger;
private final String cookieDomain;
private final boolean cookieSecure;
@Context
private Session session;
public SessionApi() {
logger = LogManager.getLogger(getClass());
cookieDomain = de.anycook.conf.Configuration.getInstance().getCookieDomain();
cookieSecure = !de.anycook.conf.Configuration.getInstance().isDeveloperMode();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
@PrivateView
public Response getSession() {
try {
return Response.accepted(session.getUser()).build();
} catch (WebApplicationException e) {
return e.getResponse();
}
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response login(@Context HttpServletRequest request,
Session.UserAuth auth) {
LoginAttempt loginAttempt = null;
try {
int userId = User.getUserId(auth.username);
if (!LoginAttempt.isLoginAllowed(userId)) {
logger.warn("too many login attempts for " + userId);
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
loginAttempt =
new LoginAttempt(userId, request.getRemoteAddr(), System.currentTimeMillis());
session.login(userId, auth.password);
loginAttempt.setSuccessful(true);
User user = session.getUser();
ResponseBuilder response = Response.ok(user);
if (auth.stayLoggedIn) {
logger.debug(String.format("stayLoggedIn"));
NewCookie cookie =
new NewCookie("anycook", session.makePermanentCookieId(user.getId()), "/",
cookieDomain,
"", 7 * 24 * 60 * 60, cookieSecure, true);
response.cookie(cookie);
}
return response.build();
} catch (User.LoginException | DBUser.UserNotFoundException e) {
throw new WebApplicationException(Response.Status.FORBIDDEN);
} catch (IOException | SQLException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} finally {
if (loginAttempt != null) {
try {
loginAttempt.save();
} catch (SQLException e) {
logger.error(e, e);
}
}
}
}
@POST
@Path("facebook")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public void facebookLogin(String signedRequest) {
try {
session.facebookLogin(signedRequest);
} catch (IOException | SQLException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (User.LoginException | DBUser.UserNotFoundException e) {
logger.warn(e, e);
throw new WebApplicationException(Response.Status.FORBIDDEN);
}
}
@DELETE
@Produces(MediaType.APPLICATION_JSON)
public Response logout(@Context HttpHeaders hh) {
Map<String, Cookie> cookies = hh.getCookies();
session.checkLogin();
ResponseBuilder response = Response.ok();
if (cookies.containsKey("anycook")) {
Cookie cookie = cookies.get("anycook");
try {
session.deleteCookieID(cookie.getValue());
} catch (SQLException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
}
NewCookie newCookie = new NewCookie(cookie, "", -1, false);
response.cookie(newCookie);
}
session.logout();
return response.entity("true").build();
}
@POST
@Path("activate")
@Produces(MediaType.APPLICATION_JSON)
public void activateAccount(@FormParam("activationkey") String activationKey) {
try {
User.activateById(activationKey);
SiteMapGenerator.generateProfileSiteMap();
} catch (SQLException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (DBUser.ActivationFailedException e) {
logger.warn(e, e);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
}
@POST
@Path("resetPassword")
@Consumes(MediaType.APPLICATION_JSON)
public void resetPasswordRequest(String mail) {
try {
User.createResetPasswordID(mail);
} catch (SQLException | IOException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (DBUser.UserNotFoundException e) {
logger.info(e);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
}
@PUT
@Path("resetPassword")
@Consumes(MediaType.APPLICATION_JSON)
public void resetPassword(PasswordReset passwordReset) {
try {
User.resetPassword(passwordReset.id, passwordReset.newPassword);
} catch (SQLException e) {
logger.error(e, e);
throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
} catch (User.ResetPasswordException e) {
logger.warn(e);
throw new WebApplicationException(Response.Status.BAD_REQUEST);
}
}
@GET
@Path("id")
@Produces(MediaType.TEXT_PLAIN)
public String getSessionId(@Context HttpServletRequest request) {
return request.getSession(true).getId();
}
public static class PasswordReset {
public String id;
public String newPassword;
}
}