001package com.box.sdk;
002
003import static com.box.sdk.http.ContentType.APPLICATION_FORM_URLENCODED;
004
005import com.eclipsesource.json.Json;
006import com.eclipsesource.json.JsonObject;
007import java.net.URL;
008
009/** Creates and manages Client Credentials Grant API connection. */
010public final class BoxCCGAPIConnection extends BoxAPIConnection {
011
012  static final String ENTERPRISE_SUBJECT_TYPE = "enterprise";
013  static final String USER_SUBJECT_TYPE = "user";
014  private String subjectType;
015  private String subjectId;
016
017  // Hiding constructor
018  private BoxCCGAPIConnection(String accessToken) {
019    super(accessToken);
020  }
021
022  // Hiding constructor
023  private BoxCCGAPIConnection(
024      String clientID, String clientSecret, String accessToken, String refreshToken) {
025    super(clientID, clientSecret, accessToken, refreshToken);
026  }
027
028  // Hiding constructor
029  private BoxCCGAPIConnection(String clientID, String clientSecret, String authCode) {
030    super(clientID, clientSecret, authCode);
031  }
032
033  // Hiding constructor
034  private BoxCCGAPIConnection(String clientID, String clientSecret) {
035    super(clientID, clientSecret);
036  }
037
038  // Hiding constructor
039  private BoxCCGAPIConnection(BoxConfig boxConfig) {
040    super(boxConfig);
041  }
042
043  /**
044   * Creates connection that authenticates as a Service Account
045   *
046   * @param clientId the client ID to use when getting the access token.
047   * @param clientSecret the client secret to use when getting the access token.
048   * @param enterpriseId the enterprise ID to use when getting the access token.
049   * @return Client Credentials Grant API connection.
050   */
051  public static BoxCCGAPIConnection applicationServiceAccountConnection(
052      String clientId, String clientSecret, String enterpriseId) {
053    BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret);
054    api.subjectType = ENTERPRISE_SUBJECT_TYPE;
055    api.subjectId = enterpriseId;
056    return api;
057  }
058
059  /**
060   * Creates connection that authenticates as a User
061   *
062   * @param clientId the client ID to use when getting the access token.
063   * @param clientSecret the client secret to use when getting the access token.
064   * @param userId the user ID to use when getting the access token.
065   * @return Client Credentials Grant API connection.
066   */
067  public static BoxCCGAPIConnection userConnection(
068      String clientId, String clientSecret, String userId) {
069    BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret);
070    api.subjectType = USER_SUBJECT_TYPE;
071    api.subjectId = userId;
072    return api;
073  }
074
075  /**
076   * Restores a BoxAPIConnection from a saved state.
077   *
078   * @param clientID the client ID to use with the connection.
079   * @param clientSecret the client secret to use with the connection.
080   * @param state the saved state that was created with {@link #save}.
081   * @return a restored API connection.
082   * @see #save
083   */
084  public static BoxCCGAPIConnection restore(String clientID, String clientSecret, String state) {
085    BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientID, clientSecret);
086    api.restore(state);
087    return api;
088  }
089
090  @Override
091  protected BoxAPIRequest createTokenRequest(URL url) {
092    String urlParameters =
093        String.format(
094            "grant_type=client_credentials&client_id=%s&client_secret=%s&box_subject_type=%s&box_subject_id=%s",
095            this.getClientID(), this.getClientSecret(), this.subjectType, this.subjectId);
096    BoxAPIRequest request = new BoxAPIRequest(this, url, "POST");
097    request.shouldAuthenticate(false);
098    request.setBody(urlParameters);
099    request.addHeader("Content-Type", APPLICATION_FORM_URLENCODED);
100    return request;
101  }
102
103  @Override
104  protected void extractTokens(JsonObject jsonObject) {
105    this.setAccessToken(jsonObject.get("access_token").asString());
106    this.setLastRefresh(System.currentTimeMillis());
107    this.setExpires(jsonObject.get("expires_in").asLong() * 1000);
108  }
109
110  @Override
111  public boolean canRefresh() {
112    return true;
113  }
114
115  public boolean isUserConnection() {
116    return subjectType.equals(USER_SUBJECT_TYPE);
117  }
118
119  @Override
120  public String save() {
121    JsonObject state = Json.parse(super.save()).asObject();
122    state.add("subjectType", this.subjectType);
123    state.add("subjectId", this.subjectId);
124    return state.toString();
125  }
126
127  @Override
128  public void restore(String state) {
129    super.restore(state);
130
131    JsonObject json = Json.parse(state).asObject();
132    this.subjectType = json.get("subjectType").asString();
133    this.subjectId = json.get("subjectId").asString();
134  }
135}