package com.authy.api; import com.authy.AuthyException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.io.StringWriter; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author Julian Camargo */ public class Users extends Resource { public static final String NEW_USER_PATH = "/protected/json/users/new"; public static final String DELETE_USER_PATH = "/protected/json/users/delete/"; public static final String SMS_PATH = "/protected/json/sms/"; public static final String ONE_CODE_CALL_PATH = "/protected/json/call/"; public static final String USER_STATUS_PATH = "/protected/json/users/%d/status"; public static final String DEFAULT_COUNTRY_CODE = "1"; public Users(String uri, String key) { super(uri, key, Resource.JSON_CONTENT_TYPE); } public Users(String uri, String key, boolean testFlag) { super(uri, key, testFlag, Resource.JSON_CONTENT_TYPE); } /** * Create a new user using his e-mail, phone and country code. * * @param email * @param phone * @param countryCode * @return a User instance */ public com.authy.api.User createUser(String email, String phone, String countryCode) throws AuthyException { User user = new User(email, phone, countryCode); final Response response = this.post(NEW_USER_PATH, user); return userFromJson(response.getStatus(), response.getBody()); } /** * Create a new user using his e-mail and phone. It uses USA country code by default. * * @param email * @param phone * @return a User instance */ public com.authy.api.User createUser(String email, String phone) throws AuthyException { return createUser(email, phone, DEFAULT_COUNTRY_CODE); } /** * Send token via sms to a user. * * @param userId * @return Hash instance with API's response. */ public Hash requestSms(int userId) throws AuthyException { return requestSms(userId, new HashMap<>(0)); } /** * Send token via sms to a user with some options defined. * * @param userId * @param options * @return Hash instance with API's response. */ public Hash requestSms(int userId, Map<String, String> options) throws AuthyException { MapToResponse opt = new MapToResponse(options); final Response response = this.get(SMS_PATH + Integer.toString(userId), opt); return instanceFromJson(response.getStatus(), response.getBody()); } /** * Send token via call to a user. * * @param userId * @return Hash instance with API's response. */ public Hash requestCall(int userId) throws AuthyException { return requestCall(userId, new HashMap<>(0)); } /** * Send token via call to a user with some options defined. * * @param userId * @param options * @return Hash instance with API's response. */ public Hash requestCall(int userId, Map<String, String> options) throws AuthyException { MapToResponse opt = new MapToResponse(options); final Response response = this.get(ONE_CODE_CALL_PATH + Integer.toString(userId), opt); return instanceFromJson(response.getStatus(), response.getBody()); } /** * Delete a user. * * @param userId * @return Hash instance with API's response. */ public Hash deleteUser(int userId) throws AuthyException { final Response response = this.post(DELETE_USER_PATH + Integer.toString(userId), null); return instanceFromJson(response.getStatus(), response.getBody()); } /** * Get user status. * * @return object containing user status */ public UserStatus requestStatus(int userId) throws AuthyException { final Response response = this.get(String.format(USER_STATUS_PATH, userId), null); UserStatus userStatus = userStatusFromJson(response); return userStatus; } private com.authy.api.User userFromJson(int status, String content) throws AuthyException { com.authy.api.User user = new com.authy.api.User(status, content); if (user.isOk()) { JSONObject userJson = new JSONObject(content); user.setId(userJson.getJSONObject("user").getInt("id")); } else { Error error = errorFromJson(content); user.setError(error); } return user; } private Hash instanceFromJson(int status, String content) throws AuthyException { Hash hash = new Hash(status, content); if (hash.isOk()) { try { JSONObject jsonResponse = new JSONObject(content); String message = jsonResponse.optString("message"); hash.setMessage(message); boolean success = jsonResponse.optBoolean("success"); hash.setSuccess(success); String token = jsonResponse.optString("token"); hash.setToken(token); } catch (JSONException e) { throw new AuthyException("Invalid response from server", e); } } else { Error error = errorFromJson(content); hash.setError(error); } return hash; } private UserStatus userStatusFromJson(Response response) throws AuthyException { UserStatus userStatus = new UserStatus(response.getStatus(), response.getBody()); if (userStatus.isOk()) { try { JSONObject jsonResponse = new JSONObject(response.getBody()); String message = jsonResponse.optString("message"); userStatus.setMessage(message); boolean success = jsonResponse.optBoolean("success"); userStatus.setSuccess(success); JSONObject status = jsonResponse.getJSONObject("status"); int userId = status.getInt("authy_id"); userStatus.setUserId(userId); boolean confirmed = status.getBoolean("confirmed"); userStatus.setConfirmed(confirmed); boolean registered = status.getBoolean("registered"); userStatus.setRegistered(registered); int countryCode = status.getInt("country_code"); userStatus.setCountryCode(countryCode); String phoneNumber = status.getString("phone_number"); userStatus.setPhoneNumber(phoneNumber); JSONArray devicesArray = status.getJSONArray("devices"); List<String> devices = userStatus.getDevices(); for (int i = 0; i < devicesArray.length(); i++) { devices.add(devicesArray.getString(i)); } } catch (JSONException e) { throw new AuthyException("Invalid response from server", e); } } else { Error error = errorFromJson(response.getBody()); userStatus.setError(error); } return userStatus; } static class MapToResponse implements Formattable { private Map<String, String> options; MapToResponse(Map<String, String> options) { this.options = options; } public String toXML() { return ""; } public Map<String, String> toMap() { return options; } } @XmlRootElement(name = "user") static class User implements Formattable { String email, cellphone, countryCode; public User() { } public User(String email, String cellphone, String countryCode) { this.email = email; this.cellphone = cellphone; this.countryCode = countryCode; } @XmlElement(name = "email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @XmlElement(name = "cellphone") public String getCellphone() { return cellphone; } public void setCellphone(String cellphone) { this.cellphone = cellphone; } @XmlElement(name = "country_code") public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } public String toXML() { StringWriter sw = new StringWriter(); String xml = ""; try { JAXBContext context = JAXBContext.newInstance(this.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.marshal(this, sw); xml = sw.toString(); } catch (JAXBException e) { e.printStackTrace(); } return xml; } public Map<String, String> toMap() { Map<String, String> map = new HashMap<>(); map.put("email", email); map.put("cellphone", cellphone); map.put("country_code", countryCode); return map; } @Override public String toJSON() { JSONObject json = new JSONObject(); json.put("user", toMap()); return json.toString(); } } }