diff --git a/src/main/resources/update/gitbucket-core_4.0.xml b/src/main/resources/update/gitbucket-core_4.0.xml
index e3368e7..04f33fe 100644
--- a/src/main/resources/update/gitbucket-core_4.0.xml
+++ b/src/main/resources/update/gitbucket-core_4.0.xml
@@ -303,6 +303,7 @@
+
diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
index d15c424..3828fbb 100644
--- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
+++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala
@@ -15,6 +15,7 @@
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.lib.Constants
import org.eclipse.jgit.lib.ObjectId
+import gitbucket.core.model.WebHookContentType
class RepositorySettingsController extends RepositorySettingsControllerBase
@@ -49,13 +50,16 @@
)(CollaboratorForm.apply)
// for web hook url addition
- case class WebHookForm(url: String, events: Set[WebHook.Event], token: Option[String])
+ case class WebHookForm(url: String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])
def webHookForm(update:Boolean) = mapping(
"url" -> trim(label("url", text(required, webHook(update)))),
"events" -> webhookEvents,
+ "ctype" -> label("ctype", text()),
"token" -> optional(trim(label("token", text(maxlength(100)))))
- )(WebHookForm.apply)
+ )(
+ (url, events, ctype, token) => WebHookForm(url, events, WebHookContentType.valueOf(ctype), token)
+ )
// for transfer ownership
case class TransferOwnerShipForm(newOwner: String)
@@ -183,7 +187,7 @@
* Display the web hook edit page.
*/
get("/:owner/:repository/settings/hooks/new")(ownerOnly { repository =>
- val webhook = WebHook(repository.owner, repository.name, "", None)
+ val webhook = WebHook(repository.owner, repository.name, "", WebHookContentType.FORM, None)
html.edithooks(webhook, Set(WebHook.Push), repository, flash.get("info"), true)
})
@@ -191,7 +195,7 @@
* Add the web hook URL.
*/
post("/:owner/:repository/settings/hooks/new", webHookForm(false))(ownerOnly { (form, repository) =>
- addWebHook(repository.owner, repository.name, form.url, form.events, form.token)
+ addWebHook(repository.owner, repository.name, form.url, form.events, form.ctype, form.token)
flash += "info" -> s"Webhook ${form.url} created"
redirect(s"/${repository.owner}/${repository.name}/settings/hooks")
})
@@ -221,7 +225,8 @@
val url = params("url")
val token = Some(params("token"))
- val dummyWebHookInfo = WebHook(repository.owner, repository.name, url, token)
+ val ctype = WebHookContentType.valueOf(params("ctype"))
+ val dummyWebHookInfo = WebHook(repository.owner, repository.name, url, ctype, token)
val dummyPayload = {
val ownerAccount = getAccountByUserName(repository.owner).get
val commits = if(repository.commitCount == 0) List.empty else git.log
@@ -280,7 +285,7 @@
* Update web hook settings.
*/
post("/:owner/:repository/settings/hooks/edit", webHookForm(true))(ownerOnly { (form, repository) =>
- updateWebHook(repository.owner, repository.name, form.url, form.events, form.token)
+ updateWebHook(repository.owner, repository.name, form.url, form.events, form.ctype, form.token)
flash += "info" -> s"webhook ${form.url} updated"
redirect(s"/${repository.owner}/${repository.name}/settings/hooks")
})
diff --git a/src/main/scala/gitbucket/core/model/WebHook.scala b/src/main/scala/gitbucket/core/model/WebHook.scala
index 9be55a8..d87f9cb 100644
--- a/src/main/scala/gitbucket/core/model/WebHook.scala
+++ b/src/main/scala/gitbucket/core/model/WebHook.scala
@@ -3,21 +3,42 @@
trait WebHookComponent extends TemplateComponent { self: Profile =>
import profile.simple._
+ implicit val whContentTypeColumnType = MappedColumnType.base[WebHookContentType, String](whct => whct.code , code => WebHookContentType.valueOf(code))
+
lazy val WebHooks = TableQuery[WebHooks]
class WebHooks(tag: Tag) extends Table[WebHook](tag, "WEB_HOOK") with BasicTemplate {
val url = column[String]("URL")
val token = column[Option[String]]("TOKEN", O.Nullable)
- def * = (userName, repositoryName, url, token) <> ((WebHook.apply _).tupled, WebHook.unapply)
+ val ctype = column[WebHookContentType]("CTYPE", O.NotNull)
+ def * = (userName, repositoryName, url, ctype, token) <> ((WebHook.apply _).tupled, WebHook.unapply)
def byPrimaryKey(owner: String, repository: String, url: String) = byRepository(owner, repository) && (this.url === url.bind)
}
}
+case class WebHookContentType(val code: String, val ctype: String)
+
+object WebHookContentType {
+ object JSON extends WebHookContentType("json", "application/json")
+
+ object FORM extends WebHookContentType("form", "application/x-www-form-urlencoded")
+
+ val values: Vector[WebHookContentType] = Vector(JSON, FORM)
+
+ private val map: Map[String, WebHookContentType] = values.map(enum => enum.code -> enum).toMap
+
+ def apply(code: String): WebHookContentType = map(code)
+
+ def valueOf(code: String): WebHookContentType = map(code)
+ def valueOpt(code: String): Option[WebHookContentType] = map.get(code)
+}
+
case class WebHook(
userName: String,
repositoryName: String,
url: String,
+ ctype: WebHookContentType,
token: Option[String]
)
diff --git a/src/main/scala/gitbucket/core/service/WebHookService.scala b/src/main/scala/gitbucket/core/service/WebHookService.scala
index 4af5ec3..0119ee1 100644
--- a/src/main/scala/gitbucket/core/service/WebHookService.scala
+++ b/src/main/scala/gitbucket/core/service/WebHookService.scala
@@ -1,7 +1,6 @@
package gitbucket.core.service
import java.io.ByteArrayInputStream
-
import fr.brouillard.oss.security.xhub.XHub
import fr.brouillard.oss.security.xhub.XHub.{XHubDigest, XHubConverter}
import gitbucket.core.api._
@@ -12,7 +11,6 @@
import gitbucket.core.util.JGitUtil.CommitInfo
import gitbucket.core.util.RepositoryName
import gitbucket.core.service.RepositoryService.RepositoryInfo
-
import org.apache.http.NameValuePair
import org.apache.http.client.entity.UrlEncodedFormEntity
import org.apache.http.message.BasicNameValuePair
@@ -22,6 +20,8 @@
import scala.concurrent._
import org.apache.http.HttpRequest
import org.apache.http.HttpResponse
+import gitbucket.core.model.WebHookContentType
+import org.apache.http.client.entity.EntityBuilder
trait WebHookService {
@@ -52,15 +52,15 @@
.map{ case (w,t) => w -> t.event }
.list.groupBy(_._1).mapValues(_.map(_._2).toSet).headOption
- def addWebHook(owner: String, repository: String, url :String, events: Set[WebHook.Event], token: Option[String])(implicit s: Session): Unit = {
- WebHooks insert WebHook(owner, repository, url, token)
+ def addWebHook(owner: String, repository: String, url :String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])(implicit s: Session): Unit = {
+ WebHooks insert WebHook(owner, repository, url, ctype, token)
events.toSet.map{ event: WebHook.Event =>
WebHookEvents insert WebHookEvent(owner, repository, url, event)
}
}
- def updateWebHook(owner: String, repository: String, url :String, events: Set[WebHook.Event], token: Option[String])(implicit s: Session): Unit = {
- WebHooks.filter(_.byPrimaryKey(owner, repository, url)).map(w => w.token).update(token)
+ def updateWebHook(owner: String, repository: String, url :String, events: Set[WebHook.Event], ctype: WebHookContentType, token: Option[String])(implicit s: Session): Unit = {
+ WebHooks.filter(_.byPrimaryKey(owner, repository, url)).map(w => (w.ctype, w.token)).update((ctype, token))
WebHookEvents.filter(_.byWebHook(owner, repository, url)).delete
events.toSet.map{ event: WebHook.Event =>
WebHookEvents insert WebHookEvent(owner, repository, url, event)
@@ -100,19 +100,29 @@
val httpClient = HttpClientBuilder.create.addInterceptorLast(itcp).build
logger.debug(s"start web hook invocation for ${webHook.url}")
val httpPost = new HttpPost(webHook.url)
- httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded")
+ logger.info(s"Content-Type: ${webHook.ctype.ctype}")
+ httpPost.addHeader("Content-Type", webHook.ctype.ctype)
httpPost.addHeader("X-Github-Event", event.name)
httpPost.addHeader("X-Github-Delivery", java.util.UUID.randomUUID().toString)
- val params: java.util.List[NameValuePair] = new java.util.ArrayList()
- params.add(new BasicNameValuePair("payload", json))
- def postContent = new UrlEncodedFormEntity(params, "UTF-8")
- httpPost.setEntity(postContent)
-
- if (!webHook.token.isEmpty) {
- // TODO find a better way and see how to extract content from postContent
- val contentAsBytes = URLEncodedUtils.format(params, "UTF-8").getBytes("UTF-8")
- httpPost.addHeader("X-Hub-Signature", XHub.generateHeaderXHubToken(XHubConverter.HEXA_LOWERCASE, XHubDigest.SHA1, webHook.token.orNull, contentAsBytes))
+ webHook.ctype match {
+ case WebHookContentType.FORM => {
+ val params: java.util.List[NameValuePair] = new java.util.ArrayList()
+ params.add(new BasicNameValuePair("payload", json))
+ def postContent = new UrlEncodedFormEntity(params, "UTF-8")
+ httpPost.setEntity(postContent)
+ if (webHook.token.exists(_.trim.nonEmpty)) {
+ // TODO find a better way and see how to extract content from postContent
+ val contentAsBytes = URLEncodedUtils.format(params, "UTF-8").getBytes("UTF-8")
+ httpPost.addHeader("X-Hub-Signature", XHub.generateHeaderXHubToken(XHubConverter.HEXA_LOWERCASE, XHubDigest.SHA1, webHook.token.get, contentAsBytes))
+ }
+ }
+ case WebHookContentType.JSON => {
+ httpPost.setEntity(EntityBuilder.create().setText(json).build())
+ if (!webHook.token.isEmpty) {
+ httpPost.addHeader("X-Hub-Signature", XHub.generateHeaderXHubToken(XHubConverter.HEXA_LOWERCASE, XHubDigest.SHA1, webHook.token.orNull, json.getBytes("UTF-8")))
+ }
+ }
}
val res = httpClient.execute(httpPost)
diff --git a/src/main/twirl/gitbucket/core/settings/edithooks.scala.html b/src/main/twirl/gitbucket/core/settings/edithooks.scala.html
index fc4f530..0767fd7 100644
--- a/src/main/twirl/gitbucket/core/settings/edithooks.scala.html
+++ b/src/main/twirl/gitbucket/core/settings/edithooks.scala.html
@@ -6,6 +6,7 @@
@import context._
@import gitbucket.core.view.helpers._
@import gitbucket.core.model.WebHook._
+@import gitbucket.core.model.WebHookContentType
@check(name: String, event: Event)={
name="@(name).@event.name" value="on" @if(events(event)){checked}
}
@@ -31,6 +32,14 @@
+