Added retrieving API token from a local property or environment variable.
This commit is contained in:
parent
87357f5127
commit
e857d3d3aa
5 changed files with 139 additions and 39 deletions
42
README.md
42
README.md
|
@ -17,7 +17,7 @@ poster.addPin("http://www.example.com/foo", "This is a test")
|
||||||
poster.deletePin("http:///www.example.com/bar")
|
poster.deletePin("http:///www.example.com/bar")
|
||||||
|
|
||||||
```
|
```
|
||||||
[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt#L203)
|
[View Example](https://github.com/ethauvin/pinboard-poster/blob/master/src/main/kotlin/net/thauvin/erik/pinboard/PinboardPoster.kt#L219)
|
||||||
|
|
||||||
### Java
|
### Java
|
||||||
```java
|
```java
|
||||||
|
@ -116,6 +116,46 @@ logger.setLevel(Level.FINE);
|
||||||
|
|
||||||
or using a logging properties file.
|
or using a logging properties file.
|
||||||
|
|
||||||
|
## API Authentication Token
|
||||||
|
|
||||||
|
The token can also be located in a [properties file](https://en.wikipedia.org/wiki/.properties) or environment variable.
|
||||||
|
|
||||||
|
### Local Property
|
||||||
|
|
||||||
|
For example, using the default `PINBOARD_API_TOKEN` key value from a `local.properties` file:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# local.properties
|
||||||
|
PINBOARD_API_TOKEN=user\:TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val poster = PinboardPoster(Paths.get("local.properties"))
|
||||||
|
```
|
||||||
|
|
||||||
|
To specify your own key:
|
||||||
|
|
||||||
|
```ini
|
||||||
|
# my.properties
|
||||||
|
my.api.key=user\:TOKEN
|
||||||
|
```
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val poster = PinboardPoster(Paths.get("my.properties"), "my.api.key")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variable
|
||||||
|
|
||||||
|
If no arguments are passed to the constructor, the `PINBOARD_API_TOKEN` environment variable will be used, if any.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export PINBOARD_API_TOKEN="user:TOKEN"
|
||||||
|
```
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val poster = PinboardPoster()
|
||||||
|
```
|
||||||
|
|
||||||
## API End Point
|
## API End Point
|
||||||
|
|
||||||
The API end point is automatically configured to `https://api.pinboard.in/v1/`. Since Pinboard uses the `del.ico.us` API, the library could potentially be used with another compatible service. To configure the API end point, use:
|
The API end point is automatically configured to `https://api.pinboard.in/v1/`. Since Pinboard uses the `del.ico.us` API, the library could potentially be used with another compatible service. To configure the API end point, use:
|
||||||
|
|
|
@ -11,9 +11,6 @@ import org.apache.maven.model.Developer
|
||||||
import org.apache.maven.model.License
|
import org.apache.maven.model.License
|
||||||
import org.apache.maven.model.Model
|
import org.apache.maven.model.Model
|
||||||
import org.apache.maven.model.Scm
|
import org.apache.maven.model.Scm
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
val bs = buildScript {
|
val bs = buildScript {
|
||||||
plugins("net.thauvin.erik:kobalt-versioneye:", "net.thauvin.erik:kobalt-maven-local:")
|
plugins("net.thauvin.erik:kobalt-versioneye:", "net.thauvin.erik:kobalt-maven-local:")
|
||||||
|
@ -26,12 +23,6 @@ val p = project {
|
||||||
artifactId = name
|
artifactId = name
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
|
||||||
val localProperties = Properties().apply {
|
|
||||||
val f = "local.properties"
|
|
||||||
if (File(f).exists()) FileInputStream(f).use { fis -> load(fis) }
|
|
||||||
}
|
|
||||||
val apiToken = localProperties.getProperty("pinboard-api-token", "")
|
|
||||||
|
|
||||||
pom = Model().apply {
|
pom = Model().apply {
|
||||||
description = project.description
|
description = project.description
|
||||||
url = "https://github.com/ethauvin/pinboard-poster"
|
url = "https://github.com/ethauvin/pinboard-poster"
|
||||||
|
@ -67,13 +58,13 @@ val p = project {
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass = "net.thauvin.erik.pinboard.PinboardPosterKt"
|
mainClass = "net.thauvin.erik.pinboard.PinboardPosterKt"
|
||||||
args(apiToken)
|
ignoreErrorStream = true
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
taskName = "runJava"
|
taskName = "runJava"
|
||||||
mainClass = "net.thauvin.erik.pinboard.JavaExample"
|
mainClass = "net.thauvin.erik.pinboard.JavaExample"
|
||||||
args(apiToken)
|
ignoreErrorStream = true
|
||||||
}
|
}
|
||||||
|
|
||||||
install {
|
install {
|
||||||
|
|
|
@ -31,15 +31,52 @@
|
||||||
*/
|
*/
|
||||||
package net.thauvin.erik.pinboard;
|
package net.thauvin.erik.pinboard;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.ConsoleHandler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class JavaExample {
|
public class JavaExample {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
final String url = "http://www.example.com/pinboard";
|
final String url = "http://www.example.com/pinboard";
|
||||||
final PinboardPoster poster = new PinboardPoster(args[0]);
|
final Path properties = Paths.get("local.properties");
|
||||||
|
final PinboardPoster poster;
|
||||||
|
|
||||||
|
if (args.length == 1) {
|
||||||
|
// API Token is an argument
|
||||||
|
poster = new PinboardPoster(args[0]);
|
||||||
|
} else if (Files.exists(properties)) {
|
||||||
|
// API Token is in local.properties (PINBOARD_API_TOKEN)
|
||||||
|
final Properties p = new Properties();
|
||||||
|
try (final InputStream stream = Files.newInputStream(properties)) {
|
||||||
|
p.load(stream);
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
poster = new PinboardPoster(p);
|
||||||
|
} else {
|
||||||
|
// API Token is an environment variable (PINBOARD_API_TOKEN) or empty
|
||||||
|
poster = new PinboardPoster();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set logging levels
|
||||||
|
final ConsoleHandler consoleHandler = new ConsoleHandler();
|
||||||
|
consoleHandler.setLevel(Level.FINE);
|
||||||
|
final Logger logger = poster.getLogger();
|
||||||
|
logger.addHandler(consoleHandler);
|
||||||
|
logger.setLevel(Level.FINE);
|
||||||
|
|
||||||
|
// Add Pin
|
||||||
if (poster.addPin(url, "Testing", "Extended test", "test kotlin")) {
|
if (poster.addPin(url, "Testing", "Extended test", "test kotlin")) {
|
||||||
System.out.println("Added: " + url);
|
System.out.println("Added: " + url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete Pin
|
||||||
if (poster.deletePin(url)) {
|
if (poster.deletePin(url)) {
|
||||||
System.out.println("Deleted: " + url);
|
System.out.println("Deleted: " + url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,16 @@
|
||||||
*/
|
*/
|
||||||
package net.thauvin.erik.pinboard
|
package net.thauvin.erik.pinboard
|
||||||
|
|
||||||
|
import net.thauvin.erik.pinboard.Constants.ENV_API_TOKEN
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import org.xml.sax.InputSource
|
import org.xml.sax.InputSource
|
||||||
import java.io.StringReader
|
import java.io.StringReader
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Paths
|
||||||
|
import java.util.*
|
||||||
import java.util.logging.ConsoleHandler
|
import java.util.logging.ConsoleHandler
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
import java.util.logging.Logger
|
import java.util.logging.Logger
|
||||||
|
@ -46,9 +50,21 @@ object Constants {
|
||||||
const val API_ENDPOINT = "https://api.pinboard.in/v1/"
|
const val API_ENDPOINT = "https://api.pinboard.in/v1/"
|
||||||
const val AUTH_TOKEN = "auth_token"
|
const val AUTH_TOKEN = "auth_token"
|
||||||
const val DONE = "done"
|
const val DONE = "done"
|
||||||
|
const val ENV_API_TOKEN = "PINBOARD_API_TOKEN"
|
||||||
}
|
}
|
||||||
|
|
||||||
open class PinboardPoster(var apiToken: String) {
|
open class PinboardPoster() {
|
||||||
|
constructor(apiToken: String) : this() {
|
||||||
|
this.apiToken = apiToken
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
constructor(properties: Properties, key: String = ENV_API_TOKEN) : this() {
|
||||||
|
this.apiToken = properties.getProperty(key, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiToken: String = if (System.getenv(ENV_API_TOKEN).isNullOrBlank()) "" else System.getenv(ENV_API_TOKEN)
|
||||||
|
|
||||||
var apiEndPoint: String = Constants.API_ENDPOINT
|
var apiEndPoint: String = Constants.API_ENDPOINT
|
||||||
|
|
||||||
val logger: Logger by lazy { Logger.getLogger(PinboardPoster::class.java.simpleName) }
|
val logger: Logger by lazy { Logger.getLogger(PinboardPoster::class.java.simpleName) }
|
||||||
|
@ -201,23 +217,37 @@ open class PinboardPoster(var apiToken: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
if (args.size == 1) {
|
val url = "http://www.example.com/pinboard"
|
||||||
val url = "http://www.example.com/pinboard"
|
val properties = Paths.get("local.properties")
|
||||||
val poster = PinboardPoster(args[0])
|
val poster = when {
|
||||||
|
args.size == 1 ->
|
||||||
|
// API Token is an argument
|
||||||
|
PinboardPoster(args[0])
|
||||||
|
Files.exists(properties) ->
|
||||||
|
// API Token is in a local.properties (PINBOARD_API_TOKEN)
|
||||||
|
PinboardPoster(
|
||||||
|
Properties().apply {
|
||||||
|
Files.newInputStream(properties).use { fis -> load(fis) }
|
||||||
|
}.getProperty(ENV_API_TOKEN, "")
|
||||||
|
)
|
||||||
|
else ->
|
||||||
|
// API Token is an environment variable (PINBOARD_API_TOKEN) or empty;
|
||||||
|
PinboardPoster()
|
||||||
|
}
|
||||||
|
|
||||||
with(poster.logger) {
|
// Set logging levels
|
||||||
addHandler(ConsoleHandler().apply { level = Level.FINE })
|
with(poster.logger) {
|
||||||
level = Level.FINE
|
addHandler(ConsoleHandler().apply { level = Level.FINE })
|
||||||
}
|
level = Level.FINE
|
||||||
|
}
|
||||||
|
|
||||||
if (poster.addPin(url, "Testing", "Extended test", "test kotlin")) {
|
// Add Pin
|
||||||
println("Added: $url")
|
if (poster.addPin(url, "Testing", "Extended test", "test kotlin")) {
|
||||||
}
|
println("Added: $url")
|
||||||
|
}
|
||||||
|
|
||||||
if (poster.deletePin(url)) {
|
// Delete Pin
|
||||||
println("Deleted: $url")
|
if (poster.deletePin(url)) {
|
||||||
}
|
println("Deleted: $url")
|
||||||
} else {
|
|
||||||
println("Please specify a valid API token. (eg. user:TOKEN)")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -41,16 +41,10 @@ class PinboardPosterTest {
|
||||||
private val url = "http://www.foo.com/"
|
private val url = "http://www.foo.com/"
|
||||||
private val desc = "This is a test."
|
private val desc = "This is a test."
|
||||||
private val localProps = Paths.get("local.properties")
|
private val localProps = Paths.get("local.properties")
|
||||||
private val apiToken = if (Files.exists(localProps)) {
|
|
||||||
val p = Properties().apply { Files.newInputStream(localProps).use { fis -> load(fis) } }
|
|
||||||
p.getProperty("pinboard-api-token", "")
|
|
||||||
} else {
|
|
||||||
System.getenv("PINBOARD_API_TOKEN")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAddPin() {
|
fun testAddPin() {
|
||||||
val poster = PinboardPoster("")
|
var poster = PinboardPoster("")
|
||||||
|
|
||||||
Assert.assertFalse(poster.addPin(url, desc), "apiToken: <blank>")
|
Assert.assertFalse(poster.addPin(url, desc), "apiToken: <blank>")
|
||||||
|
|
||||||
|
@ -60,13 +54,13 @@ class PinboardPosterTest {
|
||||||
//poster.apiToken = "foo:TESTING"
|
//poster.apiToken = "foo:TESTING"
|
||||||
//Assert.assertFalse(poster.addPin(url, desc), "apiToken: ${poster.apiToken}")
|
//Assert.assertFalse(poster.addPin(url, desc), "apiToken: ${poster.apiToken}")
|
||||||
|
|
||||||
poster.apiToken = apiToken
|
poster = pinboardPosterInstance()
|
||||||
Assert.assertTrue(poster.addPin(url, desc), "apiToken: $apiToken")
|
Assert.assertTrue(poster.addPin(url, desc), "apiToken: ${Constants.ENV_API_TOKEN}")
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDeletePin() {
|
fun testDeletePin() {
|
||||||
val poster = PinboardPoster(apiToken)
|
val poster = pinboardPosterInstance()
|
||||||
|
|
||||||
poster.apiEndPoint = ""
|
poster.apiEndPoint = ""
|
||||||
Assert.assertFalse(poster.deletePin(url), "apiEndPoint: <blank>")
|
Assert.assertFalse(poster.deletePin(url), "apiEndPoint: <blank>")
|
||||||
|
@ -76,4 +70,12 @@ class PinboardPosterTest {
|
||||||
|
|
||||||
Assert.assertFalse(poster.deletePin("foo.com"), "url: foo.com")
|
Assert.assertFalse(poster.deletePin("foo.com"), "url: foo.com")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun pinboardPosterInstance(): PinboardPoster {
|
||||||
|
return if (Files.exists(localProps)) {
|
||||||
|
PinboardPoster(Properties().apply { Files.newInputStream(localProps).use { fis -> load(fis) } })
|
||||||
|
} else {
|
||||||
|
PinboardPoster()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue