edu.uchicago.duo.service.DuoPhoneObjImpl.java Source code

Java tutorial

Introduction

Here is the source code for edu.uchicago.duo.service.DuoPhoneObjImpl.java

Source

/**
 * Copyright 2014 University of Chicago
 *
 * 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.
 *
 * Author: Daniel Yu <danielyu@uchicago.edu>
 */
package edu.uchicago.duo.service;

import com.duosecurity.client.Http;
import edu.uchicago.duo.domain.DuoAllIntegrationKeys;
import edu.uchicago.duo.domain.DuoPhone;
import edu.uchicago.duo.domain.DuoTablet;
import edu.uchicago.duo.domain.DuoToken;
import edu.uchicago.duo.web.DuoEnrollController;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Future;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service("duoPhoneService")
public class DuoPhoneObjImpl implements DuoObjInterface {

    //get log4j handler
    private static final Logger logger = Logger.getLogger(DuoEnrollController.class);
    private static final String duoPhoneApi = "/admin/v1/phones";
    private static final String duoUserApi = "/admin/v1/users";
    private static final String duoVerifyApi = "/verify/v1";
    private String apiURL;
    private Http request = null;
    @Autowired(required = true)
    private DuoAllIntegrationKeys duoAllIKeys;
    private JSONObject jResult = null;
    private JSONArray jResults = null;
    @Autowired
    private MessageSource message;

    @Override
    public String getObjByParam(String phoneNumber, String landLineExtension, String attribute) {
        String returnObj = null;

        request = genHttpRequest("GET", duoPhoneApi, "admin");
        request.addParam("number", phoneNumber);
        if (StringUtils.hasLength(landLineExtension)) {
            request.addParam("extension", landLineExtension);
        }
        request = signHttpRequest("admin");

        try {
            jResults = (JSONArray) request.executeRequest();

            switch (attribute) {
            case "username":
                JSONArray userproperty = jResults.getJSONObject(0).getJSONArray("users");
                returnObj = userproperty.getJSONObject(0).getString("username");
                break;
            }

        } catch (Exception ex) {
            logger.debug(
                    "2FA Exception - " + "Phone Not Exist!!!If triggered by Validation is a good thing, not error");
            logger.debug("2FA Exception - " + "The Error is: " + ex.toString());
        }

        return returnObj;

    }

    @Override
    public String createObjByParam(String phoneNumber, String device, String deviceOS, String tabletName,
            String landLineExtension) {
        String phoneID = null;

        request = genHttpRequest("POST", duoPhoneApi, "admin");
        if (device.equals("mobile")) {
            request.addParam("number", phoneNumber);
            request.addParam("type", device);
            request.addParam("platform", deviceOS);
        }

        if (device.equals("tablet")) {
            request.addParam("type", "mobile");
            request.addParam("platform", deviceOS);
            request.addParam("name", tabletName);
        }

        if (device.equals("landline")) {
            request.addParam("number", phoneNumber);
            request.addParam("type", "landline");
            if (StringUtils.hasLength(landLineExtension)) {
                request.addParam("extension", landLineExtension);
                request.addParam("postdelay", "6");
            }
        }

        request = signHttpRequest("admin");

        try {
            jResult = (JSONObject) request.executeRequest();
            phoneID = jResult.getString("phone_id");
            logger.debug("2FA Debug - " + "Successfully Created Phone, Type:" + device + "/Number:" + phoneNumber);
        } catch (Exception ex) {
            logger.error("2FA Error - " + "Unable to Create Duo Phone Object!!!!, Number:" + phoneNumber);
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }

        return phoneID;

    }

    @Override
    @Async
    public String getObjStatusById(String phoneId) {
        String status = "false";
        apiURL = new String();
        jResult = null;

        apiURL = duoPhoneApi + '/' + phoneId;
        request = genHttpRequest("GET", apiURL, "admin");
        request = signHttpRequest("admin");

        try {
            jResult = (JSONObject) request.executeRequest();

            if (jResult.getBoolean("activated")) {
                status = "true";
            }
        } catch (Exception ex) {
        }

        return status;
    }

    @Override
    public void associateObjs(String userId, String phoneId) {
        apiURL = new String();
        apiURL = duoUserApi + "/" + userId + "/phones";

        request = genHttpRequest("POST", apiURL, "admin");
        request.addParam("phone_id", phoneId);
        request = signHttpRequest("admin");

        try {
            request.executeRequest();
            logger.debug("2FA Debug - " + "Successfully Linked Phone/Tablet to User account");
        } catch (Exception ex) {
            logger.error("2FA Error - " + "Unable to Link Phone/Tablet to User account!!!!");
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }

    }

    @Override
    public String objActionById(String phoneId, String action) {
        String actionResult = null;
        apiURL = new String();
        jResult = null;

        switch (action) {
        case "qrCode":
            apiURL = duoPhoneApi + "/" + phoneId + "/activation_url";
            break;
        case "activationSMS":
            apiURL = duoPhoneApi + "/" + phoneId + "/send_sms_activation";
            break;
        case "installUrlSMS":
            apiURL = duoPhoneApi + "/" + phoneId + "/send_sms_installation";
            break;
        case "passcodeSMS":
            apiURL = duoPhoneApi + "/" + phoneId + "/send_sms_passcodes";
            break;
        }

        request = genHttpRequest("POST", apiURL, "admin");

        switch (action) {
        case "activationSMS":
            request.addParam("activation_msg",
                    message.getMessage("SMS.Device.Activation", null, Locale.getDefault()));
            break;
        case "installUrlSMS":
            request.addParam("installation_msg",
                    message.getMessage("SMS.Device.Installation", null, Locale.getDefault()));
            break;
        }

        request = signHttpRequest("admin");

        try {

            switch (action) {
            case "activationSMS":
                jResult = (JSONObject) request.executeRequest();
                actionResult = null;
                logger.debug("2FA Debug - " + "Activation SMS sent");
                break;
            case "qrCode":
                jResult = (JSONObject) request.executeRequest();
                actionResult = jResult.getString("activation_barcode");
                logger.debug("2FA Debug - " + "Activation QR Code generated");
                break;
            case "passcodeSMS":
                actionResult = (String) request.executeRequest();
                logger.debug("2FA Debug - " + "SMS Passcode Sent Successfully");
                break;
            case "installUrlSMS":
                jResult = (JSONObject) request.executeRequest();
                actionResult = null;
                logger.debug("2FA Debug - " + "Installation SMS sent");
                break;
            }
        } catch (Exception ex) {
            logger.error("2FA Error - " + "Object Action Failed for: " + action);
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }

        return actionResult;

    }

    /**
     * Why use UserId instead of UserName??
     *
     * 1)UserId always return SINGLE record, although Username search should
     * only have one record also...
     *
     * 2)The JSON Response code for userID search is either success or User not
     * found, easier to capture the exception?
     *
     * 3)Return a JSON object instead of JSON Array, safe one layer of parsing
     */
    @Override
    public List<DuoPhone> getAllPhones(String userId) {
        apiURL = new String();
        apiURL = duoUserApi + "/" + userId;
        request = genHttpRequest("GET", apiURL, "admin");
        request = signHttpRequest("admin");

        jResults = null;

        DuoPhone duoPhone;
        JSONArray jPhones;
        List<DuoPhone> phones = new ArrayList<>();
        String phoneNumber;
        int counter = 0;

        try {
            jResult = (JSONObject) request.executeRequest();
            jPhones = jResult.getJSONArray("phones");

            for (int p = 0; p < jPhones.length(); p++) {
                phoneNumber = jPhones.getJSONObject(p).getString("number");
                if (phoneNumber != null && !phoneNumber.isEmpty()) {

                    duoPhone = new DuoPhone();
                    duoPhone.setId(jPhones.getJSONObject(p).getString("phone_id"));
                    duoPhone.setPhoneNumber(jPhones.getJSONObject(p).getString("number"));
                    duoPhone.setPlatform(jPhones.getJSONObject(p).getString("platform"));
                    duoPhone.setType(jPhones.getJSONObject(p).getString("type"));
                    duoPhone.setActivationStatus(jPhones.getJSONObject(p).getBoolean("activated"));
                    duoPhone.setSmsPassCodeSent(jPhones.getJSONObject(p).getBoolean("sms_passcodes_sent"));

                    String capabilities = jPhones.getJSONObject(p).getJSONArray("capabilities").toString();
                    if (capabilities.toLowerCase().contains("push")) {
                        duoPhone.setCapablePush(true);
                    }
                    if (capabilities.toLowerCase().contains("sms")) {
                        duoPhone.setCapableSMS(true);
                    }
                    if (capabilities.toLowerCase().contains("phone")) {
                        duoPhone.setCapablePhone(true);
                    }

                    phones.add(duoPhone);
                    counter++;
                }

            }

        } catch (Exception ex) {
            logger.error("2FA Error - " + "Unable to Excute Method 'GetAllPhones'");
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }

        logger.debug("2FA Debug - " + "Total Number of Phones(DuoPhoneImp) " + userId + " has:" + counter);
        return phones;

    }

    @Override
    public void deleteObj(String phoneId, String na) {
        apiURL = new String();
        apiURL = duoPhoneApi + "/" + phoneId;

        request = genHttpRequest("DELETE", apiURL, "admin");
        request = signHttpRequest("admin");

        try {
            request.executeRequest();
            logger.debug("2FA Debug - " + "Successfully Deleted phone, ID=" + phoneId);
        } catch (Exception ex) {
            logger.error("2FA Error - " + "Unable to Delete Phone from Useraccount!!!");
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    private Http genHttpRequest(String getOrPost, String apiURL, String apiType) {
        request = null;
        try {
            switch (apiType) {
            case "admin":
                request = new Http(getOrPost, duoAllIKeys.getAdminikeys().getHostkey(), apiURL);
                break;
            case "verify":
                request = new Http(getOrPost, duoAllIKeys.getVerifyikeys().getHostkey(), apiURL);
                break;
            }
        } catch (Exception e) {
        }

        return request;
    }

    private Http signHttpRequest(String apiType) {

        try {
            switch (apiType) {
            case "admin":
                request.signRequest(duoAllIKeys.getAdminikeys().getIkey(), duoAllIKeys.getAdminikeys().getSkey());
                break;
            case "verify":
                request.signRequest(duoAllIKeys.getVerifyikeys().getIkey(), duoAllIKeys.getVerifyikeys().getSkey());
                break;
            }
        } catch (Exception e) {
        }

        return request;
    }
    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    public String getObjById() {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public List<DuoTablet> getAllTablets(String param1) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public List<DuoToken> getAllTokens(String param1) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public void resyncObj(String param1, String param2, String param3, String param4) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    @Override
    @Async
    public Map<String, Object> verifyObj(String pNumber, String ext, String action) {
        String txid = null;
        String pin = null;
        String info = null;
        String state = null;

        jResult = null;

        Map<String, Object> verifyInfo = new HashMap<>();

        apiURL = new String();
        apiURL = duoVerifyApi + "/" + action;

        switch (action) {
        case "call":
            request = genHttpRequest("POST", apiURL, "verify");
            request.addParam("phone", pNumber);
            if (StringUtils.hasLength(ext)) {
                request.addParam("extension", ext);
                request.addParam("postdelay", "6");
            }
            request.addParam("message", message.getMessage("CALL.Device.Verify", null, Locale.getDefault()));
            break;
        case "status":
            request = genHttpRequest("GET", apiURL, "verify");
            request.addParam("txid", pNumber);
            break;

        }

        request = signHttpRequest("verify");

        try {
            jResult = (JSONObject) request.executeRequest();

            switch (action) {
            case "call":
                txid = jResult.getString("txid");
                pin = jResult.getString("pin");
                verifyInfo.put("txid", txid);
                verifyInfo.put("pin", pin);
                logger.debug("2FA Debug - " + "DuoPhoneService.verifyObj:" + "txid=" + txid + ",Pin=" + pin);
                break;
            case "status":
                info = jResult.getString("info");
                state = jResult.getString("state");
                verifyInfo.put("info", info);
                verifyInfo.put("state", state);
                break;
            }

        } catch (Exception ex) {
            logger.error("2FA Error - " + "Unable to Call Phone!!!");
            logger.error("2FA Error - " + "The Error is(PhoneObjImp): " + ex.toString());
        }

        return verifyInfo;

    }
}