nu.yona.server.subscriptions.rest.NewDeviceRequestController.java Source code

Java tutorial

Introduction

Here is the source code for nu.yona.server.subscriptions.rest.NewDeviceRequestController.java

Source

/*******************************************************************************
 * Copyright (c) 2016, 2018 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.yona.server.subscriptions.rest;

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

import java.util.Optional;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.Resource;
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
import org.springframework.hateoas.mvc.ResourceAssemblerSupport;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import nu.yona.server.crypto.CryptoException;
import nu.yona.server.crypto.seckey.CryptoSession;
import nu.yona.server.device.rest.DeviceController;
import nu.yona.server.rest.Constants;
import nu.yona.server.rest.ControllerBase;
import nu.yona.server.rest.JsonRootRelProvider;
import nu.yona.server.subscriptions.rest.NewDeviceRequestController.NewDeviceRequestResource;
import nu.yona.server.subscriptions.service.BuddyDto;
import nu.yona.server.subscriptions.service.DeviceRequestException;
import nu.yona.server.subscriptions.service.NewDeviceRequestDto;
import nu.yona.server.subscriptions.service.NewDeviceRequestService;
import nu.yona.server.subscriptions.service.UserDto;
import nu.yona.server.subscriptions.service.UserService;
import nu.yona.server.subscriptions.service.UserServiceException;

@Controller
@ExposesResourceFor(NewDeviceRequestResource.class)
@RequestMapping(value = "/newDeviceRequests", produces = { MediaType.APPLICATION_JSON_VALUE })
public class NewDeviceRequestController extends ControllerBase {
    private static final Logger logger = LoggerFactory.getLogger(NewDeviceRequestController.class);

    @Autowired
    private UserService userService;

    @Autowired
    private NewDeviceRequestService newDeviceRequestService;

    @RequestMapping(value = "/{mobileNumber}", method = RequestMethod.PUT)
    @ResponseStatus(HttpStatus.OK)
    public void setNewDeviceRequestForUser(@RequestHeader(value = Constants.PASSWORD_HEADER) String password,
            @PathVariable String mobileNumber, @RequestBody NewDeviceRequestCreationDto newDeviceRequestCreation) {
        try {
            userService.assertValidMobileNumber(mobileNumber);
            UUID userId = userService.getUserByMobileNumber(mobileNumber).getId();
            try (CryptoSession cryptoSession = CryptoSession.start(Optional.of(password),
                    () -> userService.doPreparationsAndCheckCanAccessPrivateData(userId))) {
                newDeviceRequestService.setNewDeviceRequestForUser(userId, password,
                        newDeviceRequestCreation.getNewDeviceRequestPassword());
            }
        } catch (UserServiceException e) {
            // prevent detecting whether a mobile number exists by throwing the same exception
            logger.error("Caught UserServiceException. Mapping it to CryptoException", e);
            throw CryptoException.decryptingData();
        }
    }

    @RequestMapping(value = "/{mobileNumber}", method = RequestMethod.GET)
    @ResponseBody
    public HttpEntity<NewDeviceRequestResource> getNewDeviceRequestForUser(
            @RequestHeader(value = Constants.NEW_DEVICE_REQUEST_PASSWORD_HEADER) Optional<String> newDeviceRequestPassword,
            @PathVariable String mobileNumber) {
        try {
            userService.assertValidMobileNumber(mobileNumber);
            UserDto user = userService.getUserByMobileNumber(mobileNumber);
            return createOkResponse(
                    newDeviceRequestService.getNewDeviceRequestForUser(user.getId(), newDeviceRequestPassword),
                    createResourceAssembler(user));
        } catch (UserServiceException e) {
            // prevent detecting whether a mobile number exists by throwing the same exception
            logger.error("Caught UserServiceException. Mapping it to DeviceRequestException", e);
            throw DeviceRequestException.noDeviceRequestPresent(mobileNumber);
        }
    }

    @RequestMapping(value = "/{mobileNumber}", method = RequestMethod.DELETE)
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    public void clearNewDeviceRequestForUser(
            @RequestHeader(value = Constants.PASSWORD_HEADER) Optional<String> password,
            @PathVariable String mobileNumber) {
        try {
            userService.assertValidMobileNumber(mobileNumber);
            UUID userId = userService.getUserByMobileNumber(mobileNumber).getId();
            try (CryptoSession cryptoSession = CryptoSession.start(password,
                    () -> userService.doPreparationsAndCheckCanAccessPrivateData(userId))) {
                newDeviceRequestService.clearNewDeviceRequestForUser(userId);
            }
        } catch (UserServiceException e) {
            // prevent detecting whether a mobile number exists by throwing the same exception
            logger.error("Caught UserServiceException. Mapping it to CryptoException", e);
            throw CryptoException.decryptingData();
        }
    }

    private NewDeviceRequestResourceAssembler createResourceAssembler(UserDto user) {
        return new NewDeviceRequestResourceAssembler(user);
    }

    static ControllerLinkBuilder getNewDeviceRequestLinkBuilder(String mobileNumber) {
        NewDeviceRequestController methodOn = methodOn(NewDeviceRequestController.class);
        return linkTo(methodOn.getNewDeviceRequestForUser(null, mobileNumber));
    }

    public static class NewDeviceRequestResource extends Resource<NewDeviceRequestDto> {
        public NewDeviceRequestResource(NewDeviceRequestDto newDeviceRequest) {
            super(newDeviceRequest);
        }
    }

    public static class NewDeviceRequestResourceAssembler
            extends ResourceAssemblerSupport<NewDeviceRequestDto, NewDeviceRequestResource> {
        private final UserDto user;

        public NewDeviceRequestResourceAssembler(UserDto user) {
            super(NewDeviceRequestController.class, NewDeviceRequestResource.class);
            this.user = user;
        }

        @Override
        public NewDeviceRequestResource toResource(NewDeviceRequestDto newDeviceRequest) {
            NewDeviceRequestResource newDeviceRequestResource = instantiateResource(newDeviceRequest);
            addSelfLink(newDeviceRequestResource);
            addEditLink(newDeviceRequestResource);/* always editable */
            addUserLink(newDeviceRequestResource);
            addRegisterDeviceLink(newDeviceRequestResource);
            return newDeviceRequestResource;
        }

        @Override
        protected NewDeviceRequestResource instantiateResource(NewDeviceRequestDto newDeviceRequest) {
            return new NewDeviceRequestResource(newDeviceRequest);
        }

        private void addSelfLink(Resource<NewDeviceRequestDto> newDeviceRequestResource) {
            newDeviceRequestResource.add(NewDeviceRequestController
                    .getNewDeviceRequestLinkBuilder(user.getMobileNumber()).withSelfRel());
        }

        private void addEditLink(Resource<NewDeviceRequestDto> newDeviceRequestResource) {
            newDeviceRequestResource.add(NewDeviceRequestController
                    .getNewDeviceRequestLinkBuilder(user.getMobileNumber()).withRel(JsonRootRelProvider.EDIT_REL));
        }

        private void addUserLink(Resource<NewDeviceRequestDto> newDeviceRequestResource) {
            newDeviceRequestResource
                    .add(UserController.getPrivateUserLink(BuddyDto.USER_REL_NAME, user.getId(), Optional.empty()));
        }

        private void addRegisterDeviceLink(Resource<NewDeviceRequestDto> newDeviceRequestResource) {
            newDeviceRequestResource
                    .add(DeviceController.getRegisterDeviceLinkBuilder(user.getId()).withRel("registerDevice"));
        }
    }
}