org.tolven.restful.AccountResourcesV0.java Source code

Java tutorial

Introduction

Here is the source code for org.tolven.restful.AccountResourcesV0.java

Source

/*
 * Copyright (C) 2010 Tolven Inc
    
 * This library is free software; you can redistribute it and/or modify it under the terms of 
 * the GNU Lesser General Public License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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 Lesser General Public License for more details.
 *
 * Contact: info@tolvenhealth.com 
 *
 * @author John Churin
 * @version $Id$
 */

package org.tolven.restful;

import java.io.ByteArrayInputStream;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Locale;
import java.util.Properties;
import java.util.Set;

import javax.annotation.ManagedBean;
import javax.ejb.EJB;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext;

import org.apache.commons.codec.binary.Base64;
import org.tolven.api.security.GeneralSecurityFilter;
import org.tolven.app.MenuLocal;
import org.tolven.core.AccountDAOLocal;
import org.tolven.core.ActivationLocal;
import org.tolven.core.TolvenPropertiesLocal;
import org.tolven.core.entity.Account;
import org.tolven.core.entity.AccountType;
import org.tolven.core.entity.AccountUser;
import org.tolven.core.entity.TolvenUser;
import org.tolven.security.LoginLocal;
import org.tolven.security.TolvenPerson;
import org.tolven.security.key.UserPrivateKey;
import org.tolven.session.TolvenSessionWrapper;
import org.tolven.session.TolvenSessionWrapperFactory;
import org.tolven.util.ExceptionFormatter;

@Path("account")
@ManagedBean
public class AccountResourcesV0 {

    @EJB
    private ActivationLocal activationBean;

    @EJB
    private AccountDAOLocal accountBean;

    @EJB
    private MenuLocal menuBean;

    @EJB
    private TolvenPropertiesLocal propertyBean;

    @EJB
    private LoginLocal loginBean;

    @Context
    private HttpServletRequest request;

    /**
     * Get general information about the current account for the current user
     * @return
     */
    @Path("info")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getInfo() {
        HttpSession session = request.getSession();
        StringBuffer sb = new StringBuffer();
        sb.append("Session Attributes:\n");
        for (Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements();) {
            String attr = e.nextElement();
            sb.append("  ");
            sb.append(attr);
            sb.append("=");
            sb.append(session.getAttribute(attr));
            sb.append("\n");
        }
        Long accountUserId = (Long) session.getAttribute("accountUserId");
        if (accountUserId != null) {
            sb.append("\nUser Attributes:\n");
            AccountUser accountUser = activationBean.findAccountUser(accountUserId);
            TolvenPerson tp = getTolvenPerson();
            sb.append("  UID=");
            sb.append(tp.getUid());
            sb.append("\n");
            sb.append("  GivenName=");
            sb.append(tp.getGivenName());
            sb.append("\n");
            sb.append("  SN=");
            sb.append(tp.getSn());
            sb.append("\n");
            try {
                sb.append("  email=");
                sb.append(tp.getPrimaryMail());
                sb.append("\n");
            } catch (Exception e) {
                sb.append("Exception: " + e.getMessage());
            }
            sb.append("\nAccount Attributes:\n");
            Account account = accountUser.getAccount();
            sb.append("  accountId=");
            sb.append(account.getId());
            sb.append("\n");
            sb.append("  Title=");
            sb.append(account.getTitle());
            sb.append("\n");
            {
                Account accountTemplate = account.getAccountTemplate();
                if (accountTemplate != null) {
                    sb.append("  templateAccountId=");
                    sb.append(accountTemplate.getId());
                    sb.append("\n");
                }
            }
        }
        return sb.toString();
    }

    @SuppressWarnings("unchecked")
    private TolvenPerson getTolvenPerson() {
        TolvenPerson tp = new TolvenPerson();
        Set<String> cnSet = (Set<String>) request.getAttribute("cn");
        if (cnSet != null && !cnSet.isEmpty()) {
            tp.setCn(cnSet.iterator().next());
        }
        Set<String> dnSet = (Set<String>) request.getAttribute("dn");
        if (dnSet != null && !dnSet.isEmpty()) {
            tp.setDn(dnSet.iterator().next());
        }
        Set<String> givenNameSet = (Set<String>) request.getAttribute("givenName");
        if (givenNameSet != null && !givenNameSet.isEmpty()) {
            tp.setGivenName(givenNameSet.iterator().next());
        }
        Set<String> oSet = (Set<String>) request.getAttribute("o");
        if (oSet != null && !oSet.isEmpty()) {
            tp.setOrganizationName(oSet.iterator().next());
        }
        Set<String> ouSet = (Set<String>) request.getAttribute("ou");
        if (ouSet != null && !ouSet.isEmpty()) {
            tp.setOrganizationUnitName(ouSet.iterator().next());
        }
        Set<String> snSet = (Set<String>) request.getAttribute("sn");
        if (snSet != null && !snSet.isEmpty()) {
            tp.setSn(snSet.iterator().next());
        }
        Set<String> stSet = (Set<String>) request.getAttribute("st");
        if (stSet != null && !stSet.isEmpty()) {
            tp.setStateOrProvince(stSet.iterator().next());
        }
        Set<String> uidSet = (Set<String>) request.getAttribute("uid");
        if (uidSet != null && !uidSet.isEmpty()) {
            tp.setUid(uidSet.iterator().next());
        }
        Set<String> mailSet = (Set<String>) request.getAttribute("dn");
        if (mailSet != null) {
            tp.setMail(new ArrayList<String>(mailSet));
        }
        return tp;
    }

    /**
     * Create a new Tolven account
     * Parameters include attributes of account object.
     * Parameters can also include account properties.
     * The initialUser must be specified. This user will have the account adminitrator permission
     * and will be the user capable of "inviting" other users to the account.
     * The response status code will be "created" if the account was created.
     * The location url will contain the account id.
     */
    @Path("create")
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    @Deprecated
    public Response createAccount(@FormParam("accountType") String accountTypeName,
            @FormParam("initialUser") String initialUserString, @FormParam("title") String title,
            @FormParam("timezone") String timezone, @FormParam("locale") String localeName,
            @DefaultValue("html") @FormParam("emailFormat") String emailFormat,
            @DefaultValue("true") @FormParam("enableBackButton") String enableBackButton,
            @DefaultValue("false") @FormParam("disableAutoRefresh") String disableAutoRefresh,
            @DefaultValue("false") @FormParam("manualMetadataUpdate") String manualMetadataUpdate,
            @FormParam("property") String property, @Context SecurityContext sc,
            MultivaluedMap<String, String> formParams) {
        AccountType accountType = accountBean.findAccountTypebyKnownType(accountTypeName);
        if (accountType == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN)
                    .entity("Account Type not provided").build();
        }
        if (!accountType.isCreatable()) {
            return Response.status(Status.FORBIDDEN).type(MediaType.TEXT_PLAIN)
                    .entity("Account Type is not creatable").build();
        }
        if (initialUserString == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Missing Initial User")
                    .build();
        }
        TolvenUser initialUser = activationBean.findUser(initialUserString);
        if (initialUser == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Invalid Initial User")
                    .build();
        }
        Account account = null;
        try {
            account = accountBean.createAccount2(title, timezone, accountType);
        } catch (Exception e) {
            return Response.status(Status.INTERNAL_SERVER_ERROR).type(MediaType.TEXT_PLAIN)
                    .entity(ExceptionFormatter.toSimpleString(e, "\\n")).build();
        }
        account.setAccountType(accountType);
        account.setEmailFormat(emailFormat);
        if (localeName != null) {
            Locale[] availableLocales = Locale.getAvailableLocales();
            Locale foundLocale = null;
            for (Locale locale : availableLocales) {
                if (localeName.equalsIgnoreCase(locale.getDisplayName())) {
                    foundLocale = locale;
                    break;
                }
            }
            account.setLocale(foundLocale.getDisplayName());
        }
        account.setEnableBackButton(enableBackButton.equalsIgnoreCase("true"));
        account.setDisableAutoRefresh(disableAutoRefresh.equalsIgnoreCase("true"));
        account.setManualMetadataUpdate(manualMetadataUpdate.equalsIgnoreCase("true"));
        // Add the initial user to the account
        TolvenSessionWrapper sessionWrapper = TolvenSessionWrapperFactory.getInstance();
        PublicKey userPublicKey = sessionWrapper.getUserPublicKey();
        accountBean.addAccountUser(account, initialUser, new Date(), true, userPublicKey);
        menuBean.updateMenuStructure(account);
        URI uri = null;
        try {
            uri = new URI(URLEncoder.encode(Long.toString(account.getId()), "UTF-8"));
        } catch (Exception e) {
            return Response.status(Status.INTERNAL_SERVER_ERROR).type(MediaType.TEXT_PLAIN)
                    .entity(ExceptionFormatter.toSimpleString(e, "\\n")).build();
        }
        return Response.created(uri).type(MediaType.TEXT_PLAIN).entity(String.valueOf(account.getId())).build();
    }

    @Path("default")
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response setDefaultAccount(@FormParam("defaulted") String defaulted) {
        AccountUser accountUser = (AccountUser) request.getAttribute(GeneralSecurityFilter.ACCOUNTUSER);
        if ("true".equals(defaulted)) {
            activationBean.setDefaultAccountUser(accountUser);
        } else {
            accountUser.setDefaultAccount(false);
        }
        return Response.ok().type(MediaType.TEXT_PLAIN).build();
    }

    /**
     * Add a user to a Tolven account
     * The logged-in user must be a user on the account
     * Properties may also be added to the accountUser
     */
    @Path("user/add")
    @POST
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
    public Response addUser(@FormParam("user") String invitedUser,
            @FormParam("userX509Certificate") String invitedUserCertificate,
            @FormParam("account") String accountIdString, @FormParam("property") String property,
            @Context SecurityContext sc, MultivaluedMap<String, String> formParams) {
        if (invitedUser == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Missing User").build();
        }
        if (accountIdString == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Missing Account Id")
                    .build();
        }
        Long accountId = null;
        try {
            accountId = Long.parseLong(accountIdString);
        } catch (Exception e) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Error parsing Account Id")
                    .build();
        }
        Account account = null;
        try {
            account = accountBean.findAccount(accountId);
        } catch (Exception e) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN).entity("Invalid Account").build();
        }
        // Make sure that the new user is not already an active member of the account
        AccountUser newAccountUser = accountBean.findAccountUser(invitedUser, accountId);
        if (newAccountUser != null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN)
                    .entity("User already a member of this account").build();
        }
        Principal principal = request.getUserPrincipal();
        AccountUser inviterAccountUser = accountBean.findAccountUser(principal.getName(), account.getId());
        if (inviterAccountUser == null) {
            return Response.status(Status.BAD_REQUEST).type(MediaType.TEXT_PLAIN)
                    .entity("Inviting user must a member of this account").build();
        }
        try {
            Date now = (Date) request.getAttribute("tolvenNow");
            TolvenUser invitedTolvenUser = activationBean.findUser(invitedUser);
            if (invitedTolvenUser == null) {
                TolvenPerson tp = new TolvenPerson();
                tp.setUid(invitedUser);
                invitedTolvenUser = loginBean.activate(tp, now);
            }
            String keyAlgorithm = propertyBean.getProperty(UserPrivateKey.USER_PRIVATE_KEY_ALGORITHM_PROP);
            TolvenSessionWrapper sessionWrapper = TolvenSessionWrapperFactory.getInstance();
            PrivateKey inviterUserPrivateKey = sessionWrapper.getUserPrivateKey(keyAlgorithm);
            PublicKey invitedUserPublicKey = null;
            if (invitedUserCertificate != null) {
                byte[] userCertificateBytes = Base64
                        .decodeBase64(URLDecoder.decode(invitedUserCertificate, "UTF-8").getBytes("UTF-8"));
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
                X509Certificate x509Certificate = (X509Certificate) certificateFactory
                        .generateCertificate(new ByteArrayInputStream(userCertificateBytes));
                invitedUserPublicKey = x509Certificate.getPublicKey();
            }
            /*
             * A userPublicKey is required for the added user, in order to protect the AccountPrivateKey, which will be associated with them
             * A null key means their data will not be encrypted in the account
             */
            newAccountUser = accountBean.inviteAccountUser(account, inviterAccountUser, invitedTolvenUser, "tolven",
                    inviterUserPrivateKey, now, false); //, invitedUserPublicKey
        } catch (Exception ex) {
            return Response.status(Status.INTERNAL_SERVER_ERROR).type(MediaType.TEXT_PLAIN)
                    .entity("Adding a user to an Account must be done by a user with a UserPublicKey").build();
        }
        URI uri = null;
        try {
            uri = new URI(URLEncoder.encode(Long.toString(newAccountUser.getId()), "UTF-8"));
        } catch (Exception e) {
            return Response.status(Status.INTERNAL_SERVER_ERROR).type(MediaType.TEXT_PLAIN)
                    .entity(ExceptionFormatter.toSimpleString(e, "\\n")).build();
        }
        return Response.created(uri).type(MediaType.TEXT_PLAIN).entity(String.valueOf(newAccountUser.getId()))
                .build();
    }

    /**
     * Create or update Account Properties
     * @return
     */
    @Path("properties/set")
    @POST
    @Produces(MediaType.APPLICATION_FORM_URLENCODED)
    public Response putAccountProperties(MultivaluedMap<String, String> mvMap) {
        try {
            if (mvMap == null) {
                return Response.status(400).type(MediaType.TEXT_PLAIN).entity("No properties supplied").build();
            }
            AccountUser accountUser = (AccountUser) request.getAttribute(GeneralSecurityFilter.ACCOUNTUSER);
            if (accountUser == null) {
                throw new RuntimeException("No accountUser found");
            }
            Properties properties = new Properties();
            for (String name : mvMap.keySet()) {
                properties.setProperty(name, mvMap.getFirst(name));
            }
            accountBean.putAccountProperties(accountUser.getAccount().getId(), properties);
            return Response.ok().build();
        } catch (Exception ex) {
            return Response.status(Status.INTERNAL_SERVER_ERROR).type(MediaType.TEXT_PLAIN)
                    .entity(ExceptionFormatter.toSimpleString(ex, "\\n")).build();
        }
    }

}