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/**
010 * Creates and manages Client Credentials Grant API connection.
011 */
012public final class BoxCCGAPIConnection extends BoxAPIConnection {
013
014    static final String ENTERPRISE_SUBJECT_TYPE = "enterprise";
015    static final String USER_SUBJECT_TYPE = "user";
016    private String subjectType;
017    private String subjectId;
018
019    // Hiding constructor
020    private BoxCCGAPIConnection(String accessToken) {
021        super(accessToken);
022    }
023
024    // Hiding constructor
025    private BoxCCGAPIConnection(String clientID, String clientSecret, String accessToken, String refreshToken) {
026        super(clientID, clientSecret, accessToken, refreshToken);
027    }
028
029    // Hiding constructor
030    private BoxCCGAPIConnection(String clientID, String clientSecret, String authCode) {
031        super(clientID, clientSecret, authCode);
032    }
033
034    // Hiding constructor
035    private BoxCCGAPIConnection(String clientID, String clientSecret) {
036        super(clientID, clientSecret);
037    }
038
039    // Hiding constructor
040    private BoxCCGAPIConnection(BoxConfig boxConfig) {
041        super(boxConfig);
042    }
043
044    /**
045     * Creates connection that authenticates as a Service Account
046     *
047     * @param clientId     the client ID to use when getting the access token.
048     * @param clientSecret the client secret to use when getting the access token.
049     * @param enterpriseId the enterprise ID to use when getting the access token.
050     * @return Client Credentials Grant API connection.
051     */
052    public static BoxCCGAPIConnection applicationServiceAccountConnection(
053        String clientId, String clientSecret, String enterpriseId
054    ) {
055        BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret);
056        api.subjectType = ENTERPRISE_SUBJECT_TYPE;
057        api.subjectId = enterpriseId;
058        return api;
059    }
060
061    /**
062     * Creates connection that authenticates as a User
063     *
064     * @param clientId     the client ID to use when getting the access token.
065     * @param clientSecret the client secret to use when getting the access token.
066     * @param userId       the user ID to use when getting the access token.
067     * @return Client Credentials Grant API connection.
068     */
069    public static BoxCCGAPIConnection userConnection(String clientId, String clientSecret, String userId) {
070        BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientId, clientSecret);
071        api.subjectType = USER_SUBJECT_TYPE;
072        api.subjectId = userId;
073        return api;
074    }
075
076    /**
077     * Restores a BoxAPIConnection from a saved state.
078     *
079     * @param clientID     the client ID to use with the connection.
080     * @param clientSecret the client secret to use with the connection.
081     * @param state        the saved state that was created with {@link #save}.
082     * @return a restored API connection.
083     * @see #save
084     */
085    public static BoxCCGAPIConnection restore(String clientID, String clientSecret, String state) {
086        BoxCCGAPIConnection api = new BoxCCGAPIConnection(clientID, clientSecret);
087        api.restore(state);
088        return api;
089    }
090
091    @Override
092    protected BoxAPIRequest createTokenRequest(URL url) {
093        String urlParameters = 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}