This repository has been archived by the owner on Mar 8, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from dstieglitz/master
Began work on tests, service credentials
- Loading branch information
Showing
8 changed files
with
232 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,20 @@ | ||
grails-google-drive [](https://travis-ci.org/donbeave/grails-google-drive) | ||
=================== | ||
|
||
Grails Google Drive Plugin | ||
## Credentials setup | ||
|
||
Setup credentails from Google Developer Console. This plugin supports "Web" credentials and "Service" (non-interactive) credentials. Download the JSON credentials file from the Google console and point the config attribute `google.drive.credentials.filePath` to point to the file. You should also specify the type of credentials using `google.drive.credentials.type` with values `web` or `service`. | ||
|
||
## Scopes | ||
|
||
Specify scopes using `google.drive.scopes` and the accepted string values provided by Google. See https://developers.google.com/drive/web/scopes | ||
|
||
|
||
|
||
|
||
Copyright and license | ||
--------------------- | ||
|
||
Copyright 2013-2014 Alexey Zhokhov under the [Apache License, Version 2.0](LICENSE). Supported by [Polusharie][polusharie]. | ||
Copyright 2013-2015 Alexey Zhokhov and Dan Stieglitz under the [Apache License, Version 2.0](LICENSE). Supported by [Polusharie][polusharie]. | ||
|
||
[polusharie]: http://www.polusharie.com |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/groovy/org/grails/plugin/google/drive/JSONConfigLoader.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package org.grails.plugin.google.drive | ||
|
||
import groovy.json.JsonSlurper | ||
|
||
/** \ | ||
* Loads the JSON credential file downloaded from the Google Developers Console | ||
* Created by dstieglitz on 9/18/15. | ||
*/ | ||
class JSONConfigLoader { | ||
|
||
public static Map getConfigFromJSON(String type, File jsonFile) throws IOException { | ||
switch (type) { | ||
case 'service': | ||
return getConfigFromServiceFileJSON(jsonFile) | ||
case 'web': | ||
return getConfigFromWebApplicationJSONFile(jsonFile) | ||
default: | ||
throw new IOException("Invalid credential type specified: ${type}") | ||
} | ||
} | ||
|
||
public static Map getConfigFromWebApplicationJSONFile(File jsonFile) throws IOException { | ||
JsonSlurper slurper = new JsonSlurper() | ||
def object = slurper.parseText(jsonFile.text) | ||
|
||
return ['key' : object.web.client_id, | ||
'secret': object.web.client_secret] | ||
} | ||
|
||
public static Map getConfigFromServiceFileJSON(File jsonFile) throws IOException { | ||
JsonSlurper slurper = new JsonSlurper() | ||
def object = slurper.parseText(jsonFile.text) | ||
|
||
return ['email' : object.client_email, | ||
'privateKey': object.private_key] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
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.googleapis.auth.oauth2.GoogleCredential; | ||
import com.google.api.client.googleapis.media.MediaHttpUploader; | ||
import com.google.api.client.googleapis.media.MediaHttpUploaderProgressListener; | ||
import com.google.api.client.http.ByteArrayContent; | ||
|
@@ -29,6 +30,7 @@ | |
import com.google.api.client.http.javanet.NetHttpTransport; | ||
import com.google.api.client.json.JsonFactory; | ||
import com.google.api.client.json.jackson2.JacksonFactory; | ||
import com.google.api.client.util.SecurityUtils; | ||
import com.google.api.client.util.store.DataStore; | ||
import com.google.api.client.util.store.FileDataStoreFactory; | ||
import com.google.api.services.drive.Drive; | ||
|
@@ -42,8 +44,11 @@ | |
|
||
import java.io.IOException; | ||
import java.security.GeneralSecurityException; | ||
import java.security.PrivateKey; | ||
import java.security.spec.PKCS8EncodedKeySpec; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
/** | ||
* @author <a href='mailto:[email protected]'>Alexey Zhokhov</a> | ||
|
@@ -103,6 +108,19 @@ static Drive init(String clientId, String clientSecret, String credentialsPath, | |
return new Drive(HTTP_TRANSPORT, JSON_FACTORY, credential); | ||
} | ||
|
||
static Drive init(String emailAddress, String privateKey, List<String> scopes) throws IOException, GeneralSecurityException { | ||
|
||
GoogleCredential credential = new GoogleCredential.Builder() | ||
.setTransport(HTTP_TRANSPORT) | ||
.setJsonFactory(JSON_FACTORY) | ||
.setServiceAccountId(emailAddress) | ||
.setServiceAccountPrivateKey(PrivateKeyUtil.readPrivateKey(privateKey)) | ||
.setServiceAccountScopes(scopes) | ||
.build(); | ||
|
||
return new Drive(HTTP_TRANSPORT, JSON_FACTORY, credential); | ||
} | ||
|
||
static Credential authorize(String clientId, String clientSecret, String credentialsPath, String credentialStore, | ||
HttpTransport httpTransport, JsonFactory jsonFactory) throws IOException { | ||
GoogleClientSecrets.Details installedDetails = new GoogleClientSecrets.Details(); | ||
|
@@ -195,6 +213,10 @@ public GoogleDrive(String clientId, String clientSecret, String credentialsPath, | |
drive = init(clientId, clientSecret, credentialsPath, credentialStore); | ||
} | ||
|
||
public GoogleDrive(String emailAddress, String privateKey, List<String> scopes) throws IOException, GeneralSecurityException { | ||
drive = init(emailAddress, privateKey, scopes); | ||
} | ||
|
||
private Drive drive; | ||
|
||
public File uploadFile(java.io.File file) throws IOException { | ||
|
70 changes: 70 additions & 0 deletions
70
src/java/org/grails/plugin/google/drive/PrivateKeyUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package org.grails.plugin.google.drive; | ||
|
||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||
import org.bouncycastle.util.io.pem.PemObject; | ||
import org.bouncycastle.util.io.pem.PemReader; | ||
import sun.misc.BASE64Decoder; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.StringReader; | ||
import java.security.*; | ||
import java.security.spec.InvalidKeySpecException; | ||
import java.security.spec.PKCS8EncodedKeySpec; | ||
|
||
/** | ||
* Created by dstieglitz on 9/18/15. | ||
*/ | ||
public class PrivateKeyUtil { | ||
|
||
static { | ||
Security.addProvider(new BouncyCastleProvider()); | ||
} | ||
|
||
public static PrivateKey readPrivateKey(File keyFile) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { | ||
// read key bytes | ||
FileInputStream in = new FileInputStream(keyFile); | ||
byte[] keyBytes = new byte[in.available()]; | ||
in.read(keyBytes); | ||
in.close(); | ||
|
||
String privateKey = new String(keyBytes, "UTF-8"); | ||
privateKey = privateKey.replaceAll("(-+BEGIN RSA PRIVATE KEY-+\\r?\\n|-+END RSA PRIVATE KEY-+\\r?\\n?)", ""); | ||
|
||
// don't use this for real projects! | ||
BASE64Decoder decoder = new BASE64Decoder(); | ||
keyBytes = decoder.decodeBuffer(privateKey); | ||
|
||
// generate private key | ||
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); | ||
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); | ||
return keyFactory.generatePrivate(spec); | ||
} | ||
|
||
// public static PrivateKey readPrivateKey(String keyString) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException { | ||
// // read key bytes | ||
// byte[] keyBytes = keyString.getBytes(); | ||
// | ||
// String privateKey = new String(keyBytes, "UTF-8"); | ||
// privateKey = privateKey.replaceAll("(-+BEGIN RSA PRIVATE KEY-+\\r?\\n|-+END RSA PRIVATE KEY-+\\r?\\n?)", ""); | ||
// | ||
// // don't use this for real projects! | ||
// BASE64Decoder decoder = new BASE64Decoder(); | ||
// keyBytes = decoder.decodeBuffer(privateKey); | ||
// | ||
// // generate private key | ||
// PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); | ||
// KeyFactory keyFactory = KeyFactory.getInstance("RSA"); | ||
// return keyFactory.generatePrivate(spec); | ||
// } | ||
|
||
public static PrivateKey readPrivateKey(String keyString) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchProviderException { | ||
PemReader reader = new PemReader(new StringReader(keyString)); | ||
PemObject pemObject = reader.readPemObject(); | ||
reader.close(); | ||
KeyFactory factory = KeyFactory.getInstance("RSA", "BC"); | ||
PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(pemObject.getContent()); | ||
return factory.generatePrivate(privKeySpec); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
test/integration/google/drive/GoogleDriveServiceIntegrationSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package google.drive | ||
|
||
import grails.test.spock.IntegrationSpec | ||
import org.grails.plugin.google.drive.GoogleDriveService | ||
|
||
class GoogleDriveServiceIntegrationSpec extends IntegrationSpec { | ||
|
||
def googleDriveService | ||
|
||
def setup() { | ||
} | ||
|
||
def cleanup() { | ||
} | ||
|
||
void "test configuration"() { | ||
setup: | ||
def list | ||
|
||
when: | ||
list = googleDriveService.list() | ||
|
||
then: | ||
list.size() > 0 | ||
} | ||
} |