Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbull committed Nov 3, 2019
0 parents commit eb1f982
Show file tree
Hide file tree
Showing 23 changed files with 997 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.{kt,kts,gradle}]
indent_style = space
indent_size = 4
continuation_indent_size = 4
27 changes: 27 additions & 0 deletions .gitignore
@@ -0,0 +1,27 @@
# Hidden files
.*

# Temporary files
*~

# Git
!.git*

# EditorConfig
!.editorconfig

# IntelliJ Idea
out/
*.iml
*.ipr
*.iws

# Travis CI
!.travis.yml

# Gradle
build/

# JVM error logs
hs_err_pid*.log
replay_pid*.log
6 changes: 6 additions & 0 deletions .travis.yml
@@ -0,0 +1,6 @@
language: java
jdk:
- openjdk8

notifications:
email: false
13 changes: 13 additions & 0 deletions LICENSE
@@ -0,0 +1,13 @@
Copyright (c) 2019 Michael Bull (https://www.michael-bull.com)

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
125 changes: 125 additions & 0 deletions README.md
@@ -0,0 +1,125 @@
# Spring Boot reCAPTCHA v3 Starter

Spring Boot starter for Google's [reCAPTCHA v3][recaptcha-v3]

[![Release](https://api.bintray.com/packages/michaelbull/maven/spring-boot-starter-recaptcha/images/download.svg)](https://bintray.com/michaelbull/maven/spring-boot-starter-recaptcha/_latestVersion) [![Build Status](https://travis-ci.org/michaelbull/spring-boot-starter-recaptcha.svg?branch=master)](https://travis-ci.org/michaelbull/kotlin-retry) [![License](https://img.shields.io/github/license/michaelbull/spring-boot-starter-recaptcha.svg)](https://github.com/michaelbull/spring-boot-starter-recaptcha/blob/master/LICENSE)

## Installation

```groovy
repositories {
maven { url = 'https://dl.bintray.com/michaelbull/maven' }
}
dependencies {
compile 'com.michael-bull.spring-boot-starter-recaptcha:spring-boot-starter-recaptcha:1.0.0'
}
```

## Getting Started

#### 1. Register reCAPTCHA v3 keys

Register your application on the [key registration page][recaptcha-v3-keys].

#### 2. Add the configuration properties to your `application.yaml`:

```yaml
recaptcha.keys:
site: "<your site key>"
secret: "<your secret key>"
```

#### 3. Model the form that recaptcha exists on:

```kotlin
class RegisterForm {

var recaptchaAction: String? = "register"

var recaptchaResponseToken: String? = null

@Email
var email: String? = null
}
```


#### 4. Add a validator for your form:

```kotlin
@Component
@RequestScope
class RegisterFormValidator @Inject constructor(
private val request: HttpServletRequest,
private val recaptchaValidator: RecaptchaValidator
) : Validator {

override fun supports(clazz: Class<*>): Boolean {
return RegisterForm::class.java.isAssignableFrom(clazz)
}

override fun validate(target: Any, errors: Errors) {
val form = target as RecoverAccountForm
val action = form.recaptchaAction
val responseToken = form.recaptchaResponseToken

recaptchaValidator
.validate("recaptchaResponseToken", request, action, responseToken, errors)
.onSuccess { (_, response) -> checkResponse(response, errors) }
}

private fun checkResponse(response: SiteVerifyResponse, errors: Errors) {
val score = response.score

if (score != null && score < 0.2) {
errors.rejectValue("recaptchaResponseToken", "Score too low")
}
}
}
```

#### 5. Bind the validator in your `Controller`:

```kotlin
@Controller
class RegisterController @Inject constructor(
private val formValidator: RegisterFormValidator
) {

@InitBinder("form")
fun initFormBinder(binder: WebDataBinder) {
binder.addValidators(formValidator)
}

/* get and post handlers... */
}
```

## I18n

Error codes generated by the RecaptchaValidator can be internationalized by
adding the following entries to your `messages.properties`:

```properties
captcha.error.actionMissing=Captcha action missing.
captcha.error.incomplete=Captcha incomplete.
captcha.error.request=Failed to submit captcha.
captcha.error.responseMissing=No response from captcha service.
captcha.error.response=Error response from captcha service.
captcha.error.failed=Captcha failed. Please try again.
captcha.error.actionMismatch=Captcha action mismatch.
```

## Contributing

Bug reports and pull requests are welcome on [GitHub][github].

## License

This project is available under the terms of the ISC license. See the
[`LICENSE`](LICENSE) file for the copyright information and licensing terms.

[recaptcha-v3]: https://developers.google.com/recaptcha/docs/v3
[recaptcha-v3-keys]: https://g.co/recaptcha/v3
[github]: https://github.com/michaelbull/spring-boot-starter-recaptcha
119 changes: 119 additions & 0 deletions build.gradle.kts
@@ -0,0 +1,119 @@
import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask
import com.jfrog.bintray.gradle.BintrayExtension
import com.jfrog.bintray.gradle.tasks.BintrayUploadTask
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

val SourceSet.kotlin: SourceDirectorySet
get() = withConvention(KotlinSourceSet::class) { kotlin }

fun BintrayExtension.pkg(configure: BintrayExtension.PackageConfig.() -> Unit) {
pkg(delegateClosureOf(configure))
}

plugins {
`java-library`
`maven-publish`
kotlin("jvm") version "1.3.50"
id("com.github.ben-manes.versions") version "0.27.0"
id("com.jfrog.bintray") version "1.8.4"
id("net.researchgate.release") version "2.8.1"
id("org.jetbrains.dokka") version "0.10.0"
id("org.jetbrains.kotlin.plugin.spring") version "1.3.50"
}

repositories {
mavenCentral()
jcenter()
maven(url = "https://dl.bintray.com/michaelbull/maven")
}

dependencies {
api("com.michael-bull.kotlin-result:kotlin-result:1.1.3")
implementation(kotlin("stdlib"))
implementation("javax.inject:javax.inject:1")
implementation("org.springframework.boot:spring-boot-starter-web:2.2.0.RELEASE")
testImplementation("org.springframework.boot:spring-boot-starter-test:2.2.0.RELEASE")
}

tasks.withType<DependencyUpdatesTask> {
rejectVersionIf {
listOf("alpha", "beta", "rc", "cr", "m", "eap", "pr").any {
candidate.version.contains(it, ignoreCase = true)
}
}
}

tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs = listOf("-Xuse-experimental=kotlin.contracts.ExperimentalContracts")
}
}

tasks.withType<Test> {
failFast = true
useJUnitPlatform()
}

val dokka by tasks.existing(DokkaTask::class) {
outputFormat = "javadoc"
outputDirectory = "$buildDir/docs/javadoc"
}

val javadocJar by tasks.registering(Jar::class) {
group = LifecycleBasePlugin.BUILD_GROUP
description = "Assembles a jar archive containing the Javadoc API documentation."
archiveClassifier.set("javadoc")
dependsOn(dokka)
from(dokka.get().outputDirectory)
}

val sourcesJar by tasks.registering(Jar::class) {
group = LifecycleBasePlugin.BUILD_GROUP
description = "Assembles a jar archive containing the main classes with sources."
archiveClassifier.set("sources")
from(project.the<SourceSetContainer>().getByName("main").allSource)
}

publishing {
publications {
register("mavenJava", MavenPublication::class) {
from(components["java"])
artifact(javadocJar.get())
artifact(sourcesJar.get())
}
}
}

val bintrayUser: String? by project
val bintrayKey: String? by project

bintray {
user = bintrayUser
key = bintrayKey
setPublications("mavenJava")

pkg {
repo = "maven"
name = project.name
desc = project.description
websiteUrl = "https://github.com/michaelbull/spring-boot-starter-recaptcha"
issueTrackerUrl = "https://github.com/michaelbull/spring-boot-starter-recaptcha-retry/issues"
vcsUrl = "git@github.com:michaelbull/spring-boot-starter-recaptcha.git"
githubRepo = "michaelbull/spring-boot-starter-recaptcha"
setLicenses("ISC")
}
}

val bintrayUpload by tasks.existing(BintrayUploadTask::class) {
dependsOn("build")
dependsOn("generatePomFileForMavenJavaPublication")
dependsOn(sourcesJar)
dependsOn(javadocJar)
}

tasks.named("afterReleaseBuild") {
dependsOn(bintrayUpload)
}
2 changes: 2 additions & 0 deletions gradle.properties
@@ -0,0 +1,2 @@
group=com.michael-bull.spring-boot-starter-recaptcha
version=1.0.0-SNAPSHOT
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

0 comments on commit eb1f982

Please sign in to comment.