diff --git a/src/main/scala/gitbucket/core/api/ApiPath.scala b/src/main/scala/gitbucket/core/api/ApiPath.scala index 661ce47..dc96a7c 100644 --- a/src/main/scala/gitbucket/core/api/ApiPath.scala +++ b/src/main/scala/gitbucket/core/api/ApiPath.scala @@ -1,6 +1,13 @@ package gitbucket.core.api /** - * path for api url. if set path '/repos/aa/bb' then, expand 'http://server:post/repos/aa/bb' when converted to json. + * Path for API url. + * If set path '/repos/aa/bb' then, expand 'http://server:port/repos/aa/bb' when converted to json. */ case class ApiPath(path: String) + +/** + * Path for git repository via SSH. + * If set path '/aa/bb.git' then, expand 'git@server:port/aa/bb.git' when converted to json. + */ +case class SshPath(path: String) diff --git a/src/main/scala/gitbucket/core/api/ApiRepository.scala b/src/main/scala/gitbucket/core/api/ApiRepository.scala index 1f79072..f5d74f6 100644 --- a/src/main/scala/gitbucket/core/api/ApiRepository.scala +++ b/src/main/scala/gitbucket/core/api/ApiRepository.scala @@ -24,6 +24,7 @@ val http_url = ApiPath(s"/git/${full_name}.git") val clone_url = ApiPath(s"/git/${full_name}.git") val html_url = ApiPath(s"/${full_name}") + val ssh_url = Some(SshPath(s":${full_name}.git")) } object ApiRepository{ @@ -55,12 +56,13 @@ def forDummyPayload(owner: ApiUser): ApiRepository = ApiRepository( - name="dummy", - full_name=s"${owner.login}/dummy", - description="", - watchers=0, - forks=0, - `private`=false, - default_branch="master", - owner=owner)(true) + name = "dummy", + full_name = s"${owner.login}/dummy", + description = "", + watchers = 0, + forks = 0, + `private` = false, + default_branch = "master", + owner = owner + )(true) } diff --git a/src/main/scala/gitbucket/core/api/JsonFormat.scala b/src/main/scala/gitbucket/core/api/JsonFormat.scala index 7164cf6..6533272 100644 --- a/src/main/scala/gitbucket/core/api/JsonFormat.scala +++ b/src/main/scala/gitbucket/core/api/JsonFormat.scala @@ -10,7 +10,7 @@ object JsonFormat { - case class Context(baseUrl: String) + case class Context(baseUrl: String, sshUrl: Option[String]) val parserISO = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") @@ -40,21 +40,24 @@ FieldSerializer[ApiCommits.File]() + ApiBranchProtection.enforcementLevelSerializer - def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](format => - ( - { - case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) - case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") - }, - { - case ApiPath(path) => JString(c.baseUrl + path) - } - ) - ) + def apiPathSerializer(c: Context) = new CustomSerializer[ApiPath](_ => ({ + case JString(s) if s.startsWith(c.baseUrl) => ApiPath(s.substring(c.baseUrl.length)) + case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") + }, { + case ApiPath(path) => JString(c.baseUrl + path) + })) + + def sshPathSerializer(c: Context) = new CustomSerializer[SshPath](_ => ({ + case JString(s) if c.sshUrl.exists(sshUrl => s.startsWith(sshUrl)) => SshPath(s.substring(c.sshUrl.get.length)) + case JString(s) => throw new MappingException("Can't convert " + s + " to ApiPath") + }, { + case SshPath(path) => c.sshUrl.map { sshUrl => JString(sshUrl + path) } getOrElse JNothing + })) /** * convert object to json string */ - def apply(obj: AnyRef)(implicit c: Context): String = Serialization.write(obj)(jsonFormats + apiPathSerializer(c)) + def apply(obj: AnyRef)(implicit c: Context): String = + Serialization.write(obj)(jsonFormats + apiPathSerializer(c) + sshPathSerializer(c)) } diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index c73ed35..bb50df4 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -140,17 +140,16 @@ ldapAuthentication: Boolean, ldap: Option[Ldap], skinName: String){ - def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/")) - def sshAddress:Option[SshAddress] = - for { - host <- sshHost if ssh - } - yield SshAddress( - host, - sshPort.getOrElse(DefaultSshPort), - "git" - ) + def baseUrl(request: HttpServletRequest): String = baseUrl.fold { + val url = request.getRequestURL.toString + val len = url.length - (request.getRequestURI.length - request.getContextPath.length) + url.substring(0, len).stripSuffix("/") + } (_.stripSuffix("/")) + + def sshAddress:Option[SshAddress] = sshHost.collect { case host if ssh => + SshAddress(host, sshPort.getOrElse(DefaultSshPort), "git") + } } case class Ldap( diff --git a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala index 6d14d2c..521f139 100644 --- a/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala +++ b/src/main/scala/gitbucket/core/servlet/GitRepositoryServlet.scala @@ -156,9 +156,13 @@ logger.debug("repository:" + owner + "/" + repository) + val settings = loadSystemSettings() + val baseUrl = settings.baseUrl(request) + val sshUrl = settings.sshAddress.map { x => s"${x.genericUser}@${x.host}:${x.port}" } + if(!repository.endsWith(".wiki")){ defining(request) { implicit r => - val hook = new CommitLogHook(owner, repository, pusher, baseUrl) + val hook = new CommitLogHook(owner, repository, pusher, baseUrl, sshUrl) receivePack.setPreReceiveHook(hook) receivePack.setPostReceiveHook(hook) } @@ -166,7 +170,7 @@ if(repository.endsWith(".wiki")){ defining(request) { implicit r => - receivePack.setPostReceiveHook(new WikiCommitHook(owner, repository.stripSuffix(".wiki"), pusher, baseUrl)) + receivePack.setPostReceiveHook(new WikiCommitHook(owner, repository.stripSuffix(".wiki"), pusher, baseUrl, sshUrl)) } } } @@ -178,7 +182,7 @@ import scala.collection.JavaConverters._ -class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String) +class CommitLogHook(owner: String, repository: String, pusher: String, baseUrl: String, sshUrl: Option[String]) extends PostReceiveHook with PreReceiveHook with RepositoryService with AccountService with IssuesService with ActivityService with PullRequestService with WebHookService with WebHookPullRequestService with CommitsService { @@ -219,7 +223,7 @@ val pushedIds = scala.collection.mutable.Set[String]() commands.asScala.foreach { command => logger.debug(s"commandType: ${command.getType}, refName: ${command.getRefName}") - implicit val apiContext = api.JsonFormat.Context(baseUrl) + implicit val apiContext = api.JsonFormat.Context(baseUrl, sshUrl) val refName = command.getRefName.split("/") val branchName = refName.drop(2).mkString("/") val commits = if (refName(1) == "tags") { @@ -320,7 +324,7 @@ } -class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: String) +class WikiCommitHook(owner: String, repository: String, pusher: String, baseUrl: String, sshUrl: Option[String]) extends PostReceiveHook with WebHookService with AccountService with RepositoryService { private val logger = LoggerFactory.getLogger(classOf[WikiCommitHook]) @@ -329,7 +333,7 @@ Database() withTransaction { implicit session => try { commands.asScala.headOption.foreach { command => - implicit val apiContext = api.JsonFormat.Context(baseUrl) + implicit val apiContext = api.JsonFormat.Context(baseUrl, sshUrl) val refName = command.getRefName.split("/") val commitIds = if (refName(1) == "tags") { None diff --git a/src/main/scala/gitbucket/core/ssh/GitCommand.scala b/src/main/scala/gitbucket/core/ssh/GitCommand.scala index 9d7345d..3be9f87 100644 --- a/src/main/scala/gitbucket/core/ssh/GitCommand.scala +++ b/src/main/scala/gitbucket/core/ssh/GitCommand.scala @@ -154,7 +154,7 @@ } } -class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String) extends DefaultGitCommand(owner, repoName) +class DefaultGitReceivePack(owner: String, repoName: String, baseUrl: String, sshUrl: Option[String]) extends DefaultGitCommand(owner, repoName) with RepositoryService with AccountService with DeployKeyService { override protected def runTask(authType: AuthType): Unit = { @@ -169,7 +169,7 @@ val repository = git.getRepository val receive = new ReceivePack(repository) if (!repoName.endsWith(".wiki")) { - val hook = new CommitLogHook(owner, repoName, userName(authType), baseUrl) + val hook = new CommitLogHook(owner, repoName, userName(authType), baseUrl, sshUrl) receive.setPreReceiveHook(hook) receive.setPostReceiveHook(hook) } @@ -216,7 +216,7 @@ } -class GitCommandFactory(baseUrl: String) extends CommandFactory { +class GitCommandFactory(baseUrl: String, sshUrl: Option[String]) extends CommandFactory { private val logger = LoggerFactory.getLogger(classOf[GitCommandFactory]) override def createCommand(command: String): Command = { @@ -227,7 +227,7 @@ case SimpleCommandRegex ("upload" , repoName) if(pluginRepository(repoName)) => new PluginGitUploadPack (repoName, routing(repoName)) case SimpleCommandRegex ("receive", repoName) if(pluginRepository(repoName)) => new PluginGitReceivePack(repoName, routing(repoName)) case DefaultCommandRegex("upload" , owner, repoName) => new DefaultGitUploadPack (owner, repoName) - case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl) + case DefaultCommandRegex("receive", owner, repoName) => new DefaultGitReceivePack(owner, repoName, baseUrl, sshUrl) case _ => new UnknownCommand(command) } } diff --git a/src/main/scala/gitbucket/core/ssh/SshServerListener.scala b/src/main/scala/gitbucket/core/ssh/SshServerListener.scala index 6ff1d0e..857db45 100644 --- a/src/main/scala/gitbucket/core/ssh/SshServerListener.scala +++ b/src/main/scala/gitbucket/core/ssh/SshServerListener.scala @@ -22,7 +22,7 @@ provider.setOverwriteAllowed(false) server.setKeyPairProvider(provider) server.setPublickeyAuthenticator(new PublicKeyAuthenticator(sshAddress.genericUser)) - server.setCommandFactory(new GitCommandFactory(baseUrl)) + server.setCommandFactory(new GitCommandFactory(baseUrl, Some(s"${sshAddress.genericUser}@${sshAddress.host}:${sshAddress.port}"))) server.setShellFactory(new NoShell(sshAddress)) } diff --git a/src/main/scala/gitbucket/core/util/Implicits.scala b/src/main/scala/gitbucket/core/util/Implicits.scala index 77767a3..393dbbf 100644 --- a/src/main/scala/gitbucket/core/util/Implicits.scala +++ b/src/main/scala/gitbucket/core/util/Implicits.scala @@ -22,7 +22,8 @@ // Convert to slick session. implicit def request2Session(implicit request: HttpServletRequest): JdbcBackend#Session = Database.getSession(request) - implicit def context2ApiJsonFormatContext(implicit context: Context): JsonFormat.Context = JsonFormat.Context(context.baseUrl) + implicit def context2ApiJsonFormatContext(implicit context: Context): JsonFormat.Context = + JsonFormat.Context(context.baseUrl, context.settings.sshAddress.map { x => s"${x.genericUser}@${x.host}:${x.port}" }) implicit class RichSeq[A](private val seq: Seq[A]) extends AnyVal { @@ -77,11 +78,6 @@ def gitRepositoryPath: String = request.getRequestURI.replaceFirst("^" + quote(request.getContextPath) + "/git/", "/") - def baseUrl:String = { - val url = request.getRequestURL.toString - val len = url.length - (request.getRequestURI.length - request.getContextPath.length) - url.substring(0, len).stripSuffix("/") - } } implicit class RichSession(private val session: HttpSession) extends AnyVal { diff --git a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala index e78d229..f897123 100644 --- a/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala +++ b/src/test/scala/gitbucket/core/api/JsonFormatSpec.scala @@ -22,7 +22,7 @@ } val sha1 = "6dcb09b5b57875f334f61aebed695e2e4193db5e" val repo1Name = RepositoryName("octocat/Hello-World") - implicit val context = JsonFormat.Context("http://gitbucket.exmple.com") + implicit val context = JsonFormat.Context("http://gitbucket.exmple.com", None) val apiUser = ApiUser( login = "octocat", diff --git a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala index 101352c..a3afc82 100644 --- a/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala +++ b/src/test/scala/gitbucket/core/ssh/GitCommandSpec.scala @@ -5,7 +5,7 @@ class GitCommandFactorySpec extends FunSpec { - val factory = new GitCommandFactory("http://localhost:8080") + val factory = new GitCommandFactory("http://localhost:8080", None) describe("createCommand") { it("should return GitReceivePack when command is git-receive-pack"){