All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.robozonky.integrations.stonky.GoogleCredentialProvider Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2019 The RoboZonky Project
 *
 * 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.
 */

package com.github.robozonky.integrations.stonky;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

import com.github.robozonky.api.SessionInfo;
import com.google.api.client.auth.oauth2.AuthorizationCodeFlow;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.VerificationCodeReceiver;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.sheets.v4.SheetsScopes;
import io.vavr.control.Try;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

final class GoogleCredentialProvider implements CredentialProvider {

    private static final Logger LOGGER = LogManager.getLogger(GoogleCredentialProvider.class);

    /**
     * Global instance of the scopes required by this quickstart.
     * If modifying these scopes, delete your previously saved credentials/ folder.
     */
    private static final List SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS,
                                                             SheetsScopes.DRIVE_FILE,
                                                             SheetsScopes.DRIVE);
    private final HttpTransport transport;
    private final String host;
    private final int port;
    private final Supplier secrets;

    GoogleCredentialProvider(final HttpTransport transport, final String callbackHost, final int callbackPort) {
        this(transport, callbackHost, callbackPort, ApiKey::get);
    }

    GoogleCredentialProvider(final HttpTransport transport, final String callbackHost, final int callbackPort,
                             final Supplier secret) {
        this.transport = transport;
        this.host = callbackHost;
        this.port = callbackPort;
        this.secrets = secret;
    }

    private static Path getLocalFolder() {
        final String dirName = Properties.GOOGLE_LOCAL_FOLDER.getValue()
                .orElseThrow(() -> new IllegalStateException("Not possible."));
        return Paths.get("").resolve(dirName).toAbsolutePath();
    }

    private AuthorizationCodeFlow createFlow(final HttpTransport httpTransport) throws IOException {
        final Path localFolder = getLocalFolder();
        LOGGER.debug("Will look for Google credentials in '{}'.", localFolder);
        return new GoogleAuthorizationCodeFlow.Builder(httpTransport, Util.JSON_FACTORY, createClientSecrets(), SCOPES)
                .setDataStoreFactory(new FileDataStoreFactory(localFolder.toFile()))
                .setAccessType("offline")
                .build();
    }

    private GoogleClientSecrets createClientSecrets() {
        final byte[] key = secrets.get();
        return Try.withResources(() -> new ByteArrayInputStream(key))
                .of(s -> GoogleClientSecrets.load(Util.JSON_FACTORY, new InputStreamReader(s)))
                .getOrElseThrow((Function) IllegalStateException::new);
    }

    @Override
    public boolean credentialExists(final SessionInfo sessionInfo) {
        try {
            final AuthorizationCodeFlow flow = createFlow(transport);
            return (flow.loadCredential(sessionInfo.getUsername()) != null);
        } catch (final Exception ex) {
            throw new IllegalStateException("Failed reading Google credentials.", ex);
        }
    }

    @Override
    public Credential getCredential(final SessionInfo sessionInfo) {
        try {
            LOGGER.debug("Will listen on {}:{}.", host, port);
            final VerificationCodeReceiver receiver = new LocalServerReceiver.Builder()
                    .setHost(host)
                    .setPort(port)
                    .build();
            final AuthorizationCodeFlow flow = createFlow(transport);
            return new AuthorizationCodeInstalledApp(flow, receiver).authorize(sessionInfo.getUsername());
        } catch (final Exception ex) {
            throw new IllegalStateException("Google credential not found.", ex);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy