Package com.streamreduce.rest.resource.api

Source Code of com.streamreduce.rest.resource.api.UserResource

/*
* Copyright 2012 Nodeable Inc
*
*    Licensed under the Apache License, Version 2.0 (the "License");
*    you may not use this file except in compliance with the License.
*    You may obtain a copy of the License at
*
*        http://www.apache.org/licenses/LICENSE-2.0
*
*    Unless required by applicable law or agreed to in writing, software
*    distributed under the License is distributed on an "AS IS" BASIS,
*    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*    See the License for the specific language governing permissions and
*    limitations under the License.
*/

package com.streamreduce.rest.resource.api;

import com.google.common.collect.ImmutableMap;
import com.streamreduce.Constants;
import com.streamreduce.InvalidUserAliasException;
import com.streamreduce.core.model.Account;
import com.streamreduce.core.model.Role;
import com.streamreduce.core.model.User;
import com.streamreduce.core.service.UserService;
import com.streamreduce.core.service.exception.UserNotFoundException;
import com.streamreduce.rest.dto.response.ConstraintViolationExceptionResponseDTO;
import com.streamreduce.rest.dto.response.UserResponseDTO;
import com.streamreduce.rest.resource.ErrorMessages;
import com.streamreduce.security.Roles;
import com.streamreduce.util.JSONObjectBuilder;
import com.streamreduce.util.SecurityUtil;
import net.sf.json.JSONObject;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Map;
import java.util.Set;

@Component
@Path("api/user")
public class UserResource extends AbstractTagableSobaResource {

    @Autowired
    UserService userService;

    /**
     * Returns the currently logged in user.
     *
     * @response.representation.200.doc The currently logged in user is returned.
     * @response.representation.200.mediaType application/json
     *
     * @return The requested item.
     */
    @GET
    public Response getCurrentUser() {
        User currentUser = securityService.getCurrentUser();
        UserResponseDTO userResponseDTO = toFullDTO(currentUser);

        return Response.ok(userResponseDTO).build();
    }

    /**
     * Returns a user looked up by ID or username.
     *
     * @response.representation.200.doc The requested user is returned
     * @response.representation.200.mediaType application/json
     * @response.representation.404.doc Returned if no such user is found
     * @response.representation.404.mediaType text/plain
     *
     * @param idOrUsername the requested ID or username
     * @return The requested user or null
     */
    @GET
    @Path("{idOrUsername}")
    public Response getUser(@PathParam("idOrUsername") String idOrUsername) {

        User currentUser = securityService.getCurrentUser();
        User requestedUser;

        try {
            if (ObjectId.isValid(idOrUsername)) {
                requestedUser = userService.getUserById(new ObjectId(idOrUsername), currentUser.getAccount());
            } else {
                requestedUser = userService.getUser(idOrUsername, currentUser.getAccount());
            }
        } catch (UserNotFoundException unfe) {
            return error("No user found with the following id: " + idOrUsername, Response.status(Response.Status.NOT_FOUND));
        }

        UserResponseDTO userResponseDTO = toFullDTO(requestedUser);
        return Response.ok(userResponseDTO).build();
    }

    /**
     * The user associated to the auth token is logged out of the application and the token is invalidated.
     *
     * @response.representation.200.doc Success status is always returned.
     * @response.representation.200.mediaType text/plain
     *
     * @return response
     */
    @GET
    @Path("logout")
    public Response logout(@HeaderParam(Constants.NODEABLE_AUTH_TOKEN) String authToken) {
        securityService.logoutCurrentUser(authToken);
        return Response
                .ok()
                .build();
    }

    /**
     * Updates password for the currently logged in user.
     *
     * @response.representation.204.doc Returned if the password was updated successfully.
     * @response.representation.400.doc Returned if the password is invalid.
     * @response.representation.400.mediaType text/plain
     *
     * @return the response object
     *
     */
    @PUT
    @Path("password")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response changePassword(JSONObject json) {
        // update just the password
        User u = securityService.getCurrentUser();
        String password = getJSON(json, "password");

        // validate password
        if (!SecurityUtil.isValidPassword(password)) {
            return error(ErrorMessages.INVALID_PASSWORD_ERROR, Response.status(Response.Status.BAD_REQUEST));
        }

        u.setPassword(password);
        userService.updateUser(u);

        return Response
                .status(Response.Status.NO_CONTENT)
                .build();
    }

    /**
     * Updates the currently logged in user profile.
     *
     * @response.representation.204.doc Returned if the password was updated successfully.
     * @response.representation.400.doc If the request is empty, or if the user alias contains invalid characters.
     * @response.representation.400.mediaType text/plain
     * @response.representation.409.doc If the request is empty, or if the user alias is already in use.
     * @response.representation.409.mediaType text/plain
     * @response.representation.500.doc Returned if a general error occurs while updating the user profile.
     * @response.representation.500.mediaType text/plain
     *
     * @return the response object
     */
    @PUT
    @Path("profile")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response changeUserProfile(JSONObject json) {
        User user = securityService.getCurrentUser();

        if (isNullOrEmpty(json)) {
            return error("JSON Payload Missing.", Response.status(Response.Status.BAD_REQUEST));
        }

        // Handle alias changes
        if (json.containsKey("alias")) {
            String alias = json.getString("alias");

            if (!alias.equalsIgnoreCase(user.getAlias())) {
                if (!(userService.isAliasAvailable(user.getAccount(), alias))) {
                    ConstraintViolationExceptionResponseDTO dto = new ConstraintViolationExceptionResponseDTO();
                    dto.setViolations(ImmutableMap.of("alias", json.getString("alias") + " is already in use"));
                    return Response.status(Response.Status.CONFLICT).entity(dto).build();
                }
            }
        }

        user.mergeWithJSON(json);

        try {
            userService.updateUser(user);
        } catch (InvalidUserAliasException e) {
            ConstraintViolationExceptionResponseDTO dto = new ConstraintViolationExceptionResponseDTO();
            dto.setViolations(ImmutableMap.of("alias", e.getMessage()));
            return Response.status(Response.Status.BAD_REQUEST).entity(dto).build();
        } catch (Exception e) {
            //Something unexpected, so return a 500.
            return error(e.getMessage(), Response.status(Response.Status.INTERNAL_SERVER_ERROR));
        }

        return Response
                .status(Response.Status.NO_CONTENT)
                .build();

    }

    /**
     * Updates the account profile associated to the currently logged in user.
     *
     * @response.representation.204.doc Returned if the password was updated successfully.
     * @response.representation.401.doc Returned if the user is not an account administrator.
     * @response.representation.401.mediaType text/plain
     *
     * @param json
     * @return the response object
     */
    @PUT
    @Path("account/profile")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response changeAccountProfile(JSONObject json) {

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }

        User user = securityService.getCurrentUser();
        Account account = user.getAccount();

        account.mergeWithJSON(json);

        userService.updateAccount(account);

        return Response
                .status(Response.Status.NO_CONTENT)
                .build();
    }

    /**
     * Deletes a specific user.
     *
     * @response.representation.400.doc Returned if the user tries to delete his/her own account.
     * @response.representation.400.mediaType text/plain
     * @response.representation.401.doc Returned if the user is not an account administrator.
     * @response.representation.401.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @return the response object
     */
    @DELETE
    @Path("{userId}")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response deleteUser(@PathParam("userId") ObjectId userId) {

        User currentUser = securityService.getCurrentUser();

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }

        try {
            User user = userService.getUserById(userId, currentUser.getAccount());

            if (securityService.getCurrentUser().getId().equals(userId)) {
                return error("You can not delete yourself. Things will get better, hang in there.", Response.status(Response.Status.BAD_REQUEST));
            }

            userService.deleteUser(user);
        } catch (UserNotFoundException e) {
            return error("User not found.", Response.status(Response.Status.NOT_FOUND));
        }
        return Response.status(Response.Status.OK).build();
    }

    /**
     * Disables a user account.
     *
     * @response.representation.204.doc If the user was successfully disabled.
     * @response.representation.400.doc Returned if the user tries to disable himself.
     * @response.representation.400.mediaType text/plain
     * @response.representation.401.doc Returned if the user is not an account administrator.
     * @response.representation.401.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @return the response object
     */
    @PUT
    @Path("{userId}/disable")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response disableUser(@PathParam("userId") ObjectId userId) {

        User currentUser = securityService.getCurrentUser();

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }

        try {
            User user = userService.getUserById(userId, currentUser.getAccount());
            user.setUserStatus(User.UserStatus.DISABLED);
            user.setUserLocked(true);

            // can't disable yourself
            if (user.getId().equals(currentUser.getId())) {
                return error("You can't disable yourself", Response.status(Response.Status.BAD_REQUEST));
            }

            // TODO: need to lock this user somehow... this will do for now
            if (user.getUsername().equals(Constants.NODEABLE_SUPER_USERNAME)) {
                return error("Can't delete super user", Response.status(Response.Status.BAD_REQUEST));
            }

            userService.updateUser(user);
        } catch (UserNotFoundException e) {
            return error("User not found.", Response.status(Response.Status.NOT_FOUND));
        }
        return Response.status(Response.Status.NO_CONTENT).build();
    }

    /**
     * Enables a previously disabled user account
     *
     * @response.representation.204.doc If the user was successfully enabled.
     * @response.representation.401.doc Returned if the user is not an account administrator.
     * @response.representation.401.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @return
     */
    @PUT
    @Path("{userId}/enable")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response enableUser(@PathParam("userId") ObjectId userId) {

        User currentUser = securityService.getCurrentUser();

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }
        try {
            User user = userService.getUserById(userId, currentUser.getAccount());
            user.setUserStatus(User.UserStatus.ACTIVATED);
            user.setUserLocked(false);
            userService.updateUser(user);
        } catch (UserNotFoundException e) {
            return error("User not found.", Response.status(Response.Status.NOT_FOUND));
        }
        return Response.status(Response.Status.NO_CONTENT).build();
    }

    /**
     * Returns the currently logged in user's configuration.
     *
     * @response.representation.200.doc Returns the user's configuration preferences.
     * @response.representation.200.mediaType application/json
     *
     * @return
     */
    @GET
    @Path("config")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getConfig() {
        User currentUser = securityService.getCurrentUser();
        return Response.ok(currentUser.getConfig()).build();
    }

    /**
     * Sets the currently logged in user's configuration preferences.
     *
     * @response.representation.200.doc Returns the user's updated configuration preferences.
     * @response.representation.200.mediaType application/json
     * @response.representation.400.doc Returned if a general exception occurs.
     * @response.representation.400.mediaType text/plain
     *
     * @param jsonObject
     * @return
     */
    @POST
    @Path("config")
    @Produces(MediaType.APPLICATION_JSON)
    public Response setConfigValues(JSONObject jsonObject) {
        User currentUser = securityService.getCurrentUser();
        try {
            currentUser.appendToConfig(jsonObject);
            userService.updateUser(currentUser);
            return Response.ok(currentUser.getConfig()).build();
        } catch (Exception e) {
            return error(e.getMessage(), Response.status(Response.Status.BAD_REQUEST));
        }
    }

    /**
     * Removes a configuration preference for the currently logged in user.
     *
     * @response.representation.201.doc Returns the user's updated configuration preferences.
     * @response.representation.400.doc Returned if a general exception occurs.
     * @response.representation.400.mediaType text/plain
     * @response.representation.404.doc Returned if the configuration preference does not exist.
     * @response.representation.404.mediaType text/plain
     *
     * @param key
     * @return the response object
     */
    @DELETE
    @Path("config/{key}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response removeConfigKey(@PathParam("key") String key) {
        User currentUser = securityService.getCurrentUser();
        Map<String,Object> userConfig = currentUser.getConfig();
        if (!userConfig.containsKey(key)) {
            return error(key + " does not exist", Response.status(Response.Status.NOT_FOUND));
        }
        try {
            currentUser.removeConfigValue(key);
            userService.updateUser(currentUser);
            return Response.noContent().build();
        } catch (Exception e) {
            return error(e.getMessage(), Response.status(Response.Status.BAD_REQUEST));
        }
    }

    /**
     * Returns configuration preference values for a specific key.
     *
     * @response.representation.200.doc The configuration preference value.
     * @response.representation.200.mediaType application/json
     * @response.representation.404.doc Returned if the configuration preference does not exist.
     * @response.representation.404.mediaType text/plain
     *
     * @param key
     * @return
     */
    @GET
    @Path("config/{key}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getConfigValueByKey(@PathParam("key") String key) {
        User currentUser = securityService.getCurrentUser();
        Map<String,Object> userConfig = currentUser.getConfig();
        if (userConfig.containsKey(key)) {
            return Response.ok(
                    new JSONObjectBuilder().add(key, userConfig.get(key)).build()
            ).build();
        } else {
            return error(key + " does not exist", Response.status(Response.Status.NOT_FOUND));
        }
    }

    /**
     * Adds hashtags to a given user account.
     *
     * @response.representation.204.doc Successful update.
     * @response.representation.400.doc Returned if the hashtag payload is empty
     * @response.representation.400.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @param json
     * @return the response object
     */
    @POST
    @Path("{userId}/hashtag")
    @Consumes(MediaType.APPLICATION_JSON)
    @Override
    public Response addTag(@PathParam("userId") String userId, JSONObject json) {

        String hashtag = getJSON(json, HASHTAG);

        User currentUser = securityService.getCurrentUser();

        if (isEmpty(hashtag)) {
            return error("Hashtag payload is empty", Response.status(Response.Status.BAD_REQUEST));
        }

        try {
            User user = userService.getUserById(new ObjectId(userId), currentUser.getAccount());
            user.addHashtag(hashtag);
            userService.updateUser(user);

        } catch (UserNotFoundException e) {
            return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
        }
        return Response.noContent().build();
    }

    /**
     * Returns the hashtags associated with a given account.
     *
     * @response.representation.200.doc Hashtags associated with the user.
     * @response.representation.200.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @return
     */
    @GET
    @Path("{userId}/hashtag")
    @Override
    public Response getTags(@PathParam("userId") String userId) {

        User currentUser = securityService.getCurrentUser();

        Set<String> tags;
        try {
            User user = userService.getUserById(new ObjectId(userId), currentUser.getAccount());
            tags = user.getHashtags();

        } catch (UserNotFoundException e) {
            return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
        }

        return Response
                .ok(tags)
                .build();

    }

    /**
     * Removes a hashtag from a user account.
     *
     * @response.representation.200.doc Hashtags associated with the user.
     * @response.representation.200.mediaType text/plain
     * @response.representation.400.doc Returned if the user is not found.
     * @response.representation.400.mediaType text/plain
     * @response.representation.404.doc Returned if the user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @param hashtag
     * @return
     */
    @DELETE
    @Path("{userId}/hashtag/{tagname}")
    @Override
    public Response removeTag(@PathParam("userId") String userId, @PathParam("tagname") String hashtag) {

        if (isEmpty(hashtag)) {
            return error("Hashtag payload is empty", Response.status(Response.Status.BAD_REQUEST));
        }
        User currentUser = securityService.getCurrentUser();

        try {
            User user = userService.getUserById(new ObjectId(userId), currentUser.getAccount());
            user.removeHashtag(hashtag);
            userService.updateUser(user);

        } catch (UserNotFoundException e) {
            return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
        }
        return Response.ok().build();
    }

    /**
     * Adds a role to a given user.
     *
     * @response.representation.201.doc Role added.
     * @response.representation.201.mediaType text/plain
     * @response.representation.400.doc If the role identifier is empty.
     * @response.representation.400.mediaType text/plain
     * @response.representation.401.doc If the requesting user does not have the admin role.
     * @response.representation.401.mediaType text/plain
     * @response.representation.404.doc If the target user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @param roleId
     * @return the response object
     */
    @POST
    @Path("{userId}/roles/{roleId}")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response addRole(@PathParam("userId") ObjectId userId, @PathParam("roleId") ObjectId roleId) {

        if (isNullOrEmpty(roleId)) {
            return error(ErrorMessages.MISSING_REQUIRED_FIELD, Response.status(Response.Status.BAD_REQUEST));
        }

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }

        User currentUser = securityService.getCurrentUser();

        try {

            User user = userService.getUserById(userId, currentUser.getAccount());
            userService.addRole(user, roleId);

        } catch (UserNotFoundException e) {
            return error("User not found.", Response.status(Response.Status.NOT_FOUND));
        }

        return Response
                .status(Response.Status.CREATED)
                .build();
    }

    /**
     * Removes a role from a target user.
     *
     * @response.representation.201.doc Role added.
     * @response.representation.201.mediaType text/plain
     * @response.representation.400.doc If the role identifier is empty, or if the user tries to remove the admin role from himself/herself.
     * @response.representation.400.mediaType text/plain
     * @response.representation.401.doc If the requesting user does not have the admin role.
     * @response.representation.401.mediaType text/plain
     * @response.representation.404.doc If the target user is not found.
     * @response.representation.404.mediaType text/plain
     *
     * @param userId
     * @param roleId
     * @return the response object
     */
    @DELETE
    @Path("{userId}/roles/{roleId}")
    @Consumes(MediaType.APPLICATION_JSON)
    public Response removeRole(@PathParam("userId") ObjectId userId, @PathParam("roleId") ObjectId roleId) {

        if (isNullOrEmpty(roleId)) {
            return error(ErrorMessages.MISSING_REQUIRED_FIELD, Response.status(Response.Status.BAD_REQUEST));
        }

        // require admin role
        if (!securityService.hasRole(Roles.ADMIN_ROLE)) {
            return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.UNAUTHORIZED));
        }

        User currentUser = securityService.getCurrentUser();

        try {

            Role adminRole = securityService.findRole(Roles.ADMIN_ROLE);
            if (currentUser.getId().equals(userId) && adminRole.getId().equals(roleId)) {
                // you can't remove the admin role from yourself!
                return error("You can not remove the administrator role from your own user.", Response.status(Response.Status.BAD_REQUEST));
            }

            User user = userService.getUserById(userId, currentUser.getAccount());
            userService.removeRole(user, roleId);

        } catch (UserNotFoundException e) {
            return error("User not found.", Response.status(Response.Status.NOT_FOUND));
        }

        return Response
                .ok()
                .build();
    }

}
TOP

Related Classes of com.streamreduce.rest.resource.api.UserResource

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.