/* * 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; } }