Package com.commafeed.frontend.resource

Source Code of com.commafeed.frontend.resource.UserREST

package com.commafeed.frontend.resource;

import io.dropwizard.hibernate.UnitOfWork;
import io.dropwizard.jersey.validation.ValidationErrorMessage;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.UUID;

import javax.inject.Inject;
import javax.inject.Singleton;
import javax.validation.ConstraintViolation;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.http.client.utils.URIBuilder;

import com.commafeed.CommaFeedApplication;
import com.commafeed.CommaFeedConfiguration;
import com.commafeed.backend.dao.UserDAO;
import com.commafeed.backend.dao.UserRoleDAO;
import com.commafeed.backend.dao.UserSettingsDAO;
import com.commafeed.backend.feed.FeedUtils;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole;
import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings.ReadingMode;
import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.backend.model.UserSettings.ViewMode;
import com.commafeed.backend.service.MailService;
import com.commafeed.backend.service.PasswordEncryptionService;
import com.commafeed.backend.service.UserService;
import com.commafeed.frontend.auth.SecurityCheck;
import com.commafeed.frontend.model.Settings;
import com.commafeed.frontend.model.UserModel;
import com.commafeed.frontend.model.request.LoginRequest;
import com.commafeed.frontend.model.request.PasswordResetRequest;
import com.commafeed.frontend.model.request.ProfileModificationRequest;
import com.commafeed.frontend.model.request.RegistrationRequest;
import com.commafeed.frontend.session.SessionHelper;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;

@Path("/user")
@Api(value = "/user", description = "Operations about the user")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Slf4j
@RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@Singleton
public class UserREST {

  private final UserDAO userDAO;
  private final UserRoleDAO userRoleDAO;
  private final UserSettingsDAO userSettingsDAO;
  private final UserService userService;
  private final PasswordEncryptionService encryptionService;
  private final MailService mailService;
  private final CommaFeedConfiguration config;

  @Path("/settings")
  @GET
  @UnitOfWork
  @ApiOperation(value = "Retrieve user settings", notes = "Retrieve user settings", response = Settings.class)
  public Response getSettings(@SecurityCheck User user) {
    Settings s = new Settings();
    UserSettings settings = userSettingsDAO.findByUser(user);
    if (settings != null) {
      s.setReadingMode(settings.getReadingMode().name());
      s.setReadingOrder(settings.getReadingOrder().name());
      s.setViewMode(settings.getViewMode().name());
      s.setShowRead(settings.isShowRead());

      s.setEmail(settings.isEmail());
      s.setGmail(settings.isGmail());
      s.setFacebook(settings.isFacebook());
      s.setTwitter(settings.isTwitter());
      s.setGoogleplus(settings.isGoogleplus());
      s.setTumblr(settings.isTumblr());
      s.setPocket(settings.isPocket());
      s.setInstapaper(settings.isInstapaper());
      s.setBuffer(settings.isBuffer());
      s.setReadability(settings.isReadability());

      s.setScrollMarks(settings.isScrollMarks());
      s.setTheme(settings.getTheme());
      s.setCustomCss(settings.getCustomCss());
      s.setLanguage(settings.getLanguage());
      s.setScrollSpeed(settings.getScrollSpeed());
    } else {
      s.setReadingMode(ReadingMode.unread.name());
      s.setReadingOrder(ReadingOrder.desc.name());
      s.setViewMode(ViewMode.title.name());
      s.setShowRead(true);
      s.setTheme("default");

      s.setEmail(true);
      s.setGmail(true);
      s.setFacebook(true);
      s.setTwitter(true);
      s.setGoogleplus(true);
      s.setTumblr(true);
      s.setPocket(true);
      s.setInstapaper(true);
      s.setBuffer(true);
      s.setReadability(true);

      s.setScrollMarks(true);
      s.setLanguage("en");
      s.setScrollSpeed(400);
    }
    return Response.ok(s).build();
  }

  @Path("/settings")
  @POST
  @UnitOfWork
  @ApiOperation(value = "Save user settings", notes = "Save user settings")
  public Response saveSettings(@SecurityCheck User user, @ApiParam(required = true) Settings settings) {
    Preconditions.checkNotNull(settings);

    UserSettings s = userSettingsDAO.findByUser(user);
    if (s == null) {
      s = new UserSettings();
      s.setUser(user);
    }
    s.setReadingMode(ReadingMode.valueOf(settings.getReadingMode()));
    s.setReadingOrder(ReadingOrder.valueOf(settings.getReadingOrder()));
    s.setShowRead(settings.isShowRead());
    s.setViewMode(ViewMode.valueOf(settings.getViewMode()));
    s.setScrollMarks(settings.isScrollMarks());
    s.setTheme(settings.getTheme());
    s.setCustomCss(settings.getCustomCss());
    s.setLanguage(settings.getLanguage());
    s.setScrollSpeed(settings.getScrollSpeed());

    s.setEmail(settings.isEmail());
    s.setGmail(settings.isGmail());
    s.setFacebook(settings.isFacebook());
    s.setTwitter(settings.isTwitter());
    s.setGoogleplus(settings.isGoogleplus());
    s.setTumblr(settings.isTumblr());
    s.setPocket(settings.isPocket());
    s.setInstapaper(settings.isInstapaper());
    s.setBuffer(settings.isBuffer());
    s.setReadability(settings.isReadability());

    userSettingsDAO.saveOrUpdate(s);
    return Response.ok().build();

  }

  @Path("/profile")
  @GET
  @UnitOfWork
  @ApiOperation(value = "Retrieve user's profile", response = UserModel.class)
  public Response get(@SecurityCheck User user) {
    UserModel userModel = new UserModel();
    userModel.setId(user.getId());
    userModel.setName(user.getName());
    userModel.setEmail(user.getEmail());
    userModel.setEnabled(!user.isDisabled());
    userModel.setApiKey(user.getApiKey());
    for (UserRole role : userRoleDAO.findAll(user)) {
      if (role.getRole() == Role.ADMIN) {
        userModel.setAdmin(true);
      }
    }
    return Response.ok(userModel).build();
  }

  @Path("/profile")
  @POST
  @UnitOfWork
  @ApiOperation(value = "Save user's profile")
  public Response save(@SecurityCheck User user, @ApiParam(required = true) ProfileModificationRequest request) {
    Preconditions.checkArgument(StringUtils.isBlank(request.getPassword()) || request.getPassword().length() >= 6);
    if (StringUtils.isNotBlank(request.getEmail())) {
      User u = userDAO.findByEmail(request.getEmail());
      Preconditions.checkArgument(u == null || user.getId().equals(u.getId()));
    }

    if (CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
      return Response.status(Status.FORBIDDEN).build();
    }

    user.setEmail(StringUtils.trimToNull(request.getEmail()));
    if (StringUtils.isNotBlank(request.getPassword())) {
      byte[] password = encryptionService.getEncryptedPassword(request.getPassword(), user.getSalt());
      user.setPassword(password);
      user.setApiKey(userService.generateApiKey(user));
    }
    if (request.isNewApiKey()) {
      user.setApiKey(userService.generateApiKey(user));
    }
    userDAO.merge(user);
    return Response.ok().build();
  }

  @Path("/register")
  @POST
  @UnitOfWork
  @ApiOperation(value = "Register a new account")
  public Response register(@Valid @ApiParam(required = true) RegistrationRequest req, @Context SessionHelper sessionHelper) {
    try {
      User registeredUser = userService.register(req.getName(), req.getPassword(), req.getEmail(), Arrays.asList(Role.USER));
      userService.login(req.getName(), req.getPassword());
      sessionHelper.setLoggedInUser(registeredUser);
      return Response.ok().build();
    } catch (final IllegalArgumentException e) {
      return Response.status(422).entity(new ValidationErrorMessage(Collections.<ConstraintViolation<?>> emptySet()) {
        @Override
        public ImmutableList<String> getErrors() {
          return ImmutableList.of(e.getMessage());
        }
      }).build();
    }
  }

  @Path("/login")
  @POST
  @UnitOfWork
  @ApiOperation(value = "Login and create a session")
  public Response login(@ApiParam(required = true) LoginRequest req, @Context SessionHelper sessionHelper) {
    Optional<User> user = userService.login(req.getName(), req.getPassword());
    if (user.isPresent()) {
      sessionHelper.setLoggedInUser(user.get());
      return Response.ok().build();
    } else {
      return Response.status(Response.Status.UNAUTHORIZED).entity("wrong username or password").build();
    }
  }

  @Path("/passwordReset")
  @POST
  @UnitOfWork
  @ApiOperation(value = "send a password reset email")
  public Response sendPasswordReset(@Valid PasswordResetRequest req) {
    User user = userDAO.findByEmail(req.getEmail());
    if (user == null) {
      return Response.status(Status.PRECONDITION_FAILED).entity("Email not found.").build();
    }
    try {
      user.setRecoverPasswordToken(DigestUtils.sha1Hex(UUID.randomUUID().toString()));
      user.setRecoverPasswordTokenDate(new Date());
      userDAO.saveOrUpdate(user);
      mailService.sendMail(user, "Password recovery", buildEmailContent(user));
      return Response.ok().build();
    } catch (Exception e) {
      log.error(e.getMessage(), e);
      return Response.status(Status.INTERNAL_SERVER_ERROR).entity("could not send email: " + e.getMessage()).build();
    }
  }

  private String buildEmailContent(User user) throws Exception {
    String publicUrl = FeedUtils.removeTrailingSlash(config.getApplicationSettings().getPublicUrl());
    publicUrl += "/rest/user/passwordResetCallback";
    return String
        .format("You asked for password recovery for account '%s', <a href='%s'>follow this link</a> to change your password. Ignore this if you didn't request a password recovery.",
            user.getName(), callbackUrl(user, publicUrl));
  }

  private String callbackUrl(User user, String publicUrl) throws Exception {
    return new URIBuilder(publicUrl).addParameter("email", user.getEmail()).addParameter("token", user.getRecoverPasswordToken())
        .build().toURL().toString();
  }

  @Path("/passwordResetCallback")
  @GET
  @UnitOfWork
  @Produces(MediaType.TEXT_HTML)
  public Response passwordRecoveryCallback(@QueryParam("email") String email, @QueryParam("token") String token) {
    Preconditions.checkNotNull(email);
    Preconditions.checkNotNull(token);

    User user = userDAO.findByEmail(email);
    if (user == null) {
      return Response.status(Status.UNAUTHORIZED).entity("Email not found.").build();
    }
    if (user.getRecoverPasswordToken() == null || !user.getRecoverPasswordToken().equals(token)) {
      return Response.status(Status.UNAUTHORIZED).entity("Invalid token.").build();
    }
    if (user.getRecoverPasswordTokenDate().before(DateUtils.addDays(new Date(), -2))) {
      return Response.status(Status.UNAUTHORIZED).entity("token expired.").build();
    }

    String passwd = RandomStringUtils.randomAlphanumeric(10);
    byte[] encryptedPassword = encryptionService.getEncryptedPassword(passwd, user.getSalt());
    user.setPassword(encryptedPassword);
    if (StringUtils.isNotBlank(user.getApiKey())) {
      user.setApiKey(userService.generateApiKey(user));
    }
    user.setRecoverPasswordToken(null);
    user.setRecoverPasswordTokenDate(null);
    userDAO.saveOrUpdate(user);

    String message = "Your new password is: " + passwd;
    message += "<br />";
    message += String.format("<a href=\"%s\">Back to Homepage</a>", config.getApplicationSettings().getPublicUrl());
    return Response.ok(message).build();
  }

  @Path("/profile/deleteAccount")
  @POST
  @UnitOfWork
  @ApiOperation(value = "Delete the user account")
  public Response delete(@SecurityCheck User user) {
    if (CommaFeedApplication.USERNAME_ADMIN.equals(user.getName()) || CommaFeedApplication.USERNAME_DEMO.equals(user.getName())) {
      return Response.status(Status.FORBIDDEN).build();
    }
    userService.unregister(userDAO.findById(user.getId()));
    return Response.ok().build();
  }
}
TOP

Related Classes of com.commafeed.frontend.resource.UserREST

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.