From 68d090f81a5746b4e5e0e6b281f32dcddb871790 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Sat, 22 Apr 2017 21:17:37 +0900 Subject: [PATCH 01/31] Show CommitStatus in commits page. --- .../RepositoryViewerController.scala | 19 ++++++-- .../gitbucket/core/repo/commits.scala.html | 43 ++++++++++++++++++- 2 files changed, 57 insertions(+), 5 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index 6fc90d7e9..eea15782f 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -13,7 +13,7 @@ import gitbucket.core.util.StringUtil._ import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.Implicits._ import gitbucket.core.util.Directory._ -import gitbucket.core.model.{Account, WebHook} +import gitbucket.core.model.{Account, CommitState, CommitStatus, WebHook} import gitbucket.core.service.WebHookService._ import gitbucket.core.view import gitbucket.core.view.helpers @@ -157,13 +157,24 @@ trait RepositoryViewerControllerBase extends ControllerBase { val (branchName, path) = repository.splitPath(multiParams("splat").head) val page = params.get("page").flatMap(_.toIntOpt).getOrElse(1) + def getStatuses(sha: String): List[CommitStatus] = { + getCommitStatues(repository.owner, repository.name, sha) + } + + def getSummary(statuses: List[CommitStatus]): (CommitState, String) = { + val stateMap = statuses.groupBy(_.state) + val state = CommitState.combine(stateMap.keySet) + val summary = stateMap.map{ case (keyState, states) => states.size+" "+keyState.name }.mkString(", ") + state -> summary + } + using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => JGitUtil.getCommitLog(git, branchName, page, 30, path) match { case Right((logs, hasNext)) => html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository, logs.splitWith{ (commit1, commit2) => view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime) - }, page, hasNext, hasDeveloperRole(repository.owner, repository.name, context.loginAccount)) + }, page, hasNext, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), getStatuses, getSummary) case Left(_) => NotFound() } } @@ -670,11 +681,11 @@ trait RepositoryViewerControllerBase extends ControllerBase { private def archiveRepository(name: String, suffix: String, repository: RepositoryService.RepositoryInfo): Unit = { val revision = name.stripSuffix(suffix) - + using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git => val oid = git.getRepository.resolve(revision) val revCommit = JGitUtil.getRevCommitFromId(git, oid) - val sha1 = oid.getName() + val sha1 = oid.getName() val repositorySuffix = (if(sha1.startsWith(revision)) sha1 else revision).replace('/','-') val filename = repository.name + "-" + repositorySuffix + suffix diff --git a/src/main/twirl/gitbucket/core/repo/commits.scala.html b/src/main/twirl/gitbucket/core/repo/commits.scala.html index 0eca2c95b..69d72a0af 100644 --- a/src/main/twirl/gitbucket/core/repo/commits.scala.html +++ b/src/main/twirl/gitbucket/core/repo/commits.scala.html @@ -4,7 +4,9 @@ commits: Seq[Seq[gitbucket.core.util.JGitUtil.CommitInfo]], page: Int, hasNext: Boolean, - hasWritePermission: Boolean)(implicit context: gitbucket.core.controller.Context) + hasWritePermission: Boolean, + getStatuses: String => List[gitbucket.core.model.CommitStatus], + getSummary: List[gitbucket.core.model.CommitStatus] => (gitbucket.core.model.CommitState, String))(implicit context: gitbucket.core.controller.Context) @import gitbucket.core.view.helpers @gitbucket.core.html.main(s"${repository.owner}/${repository.name}", Some(repository)) { @gitbucket.core.html.menu("files", repository){ @@ -63,6 +65,30 @@ } @helpers.user(commit.committerName, commit.committerEmailAddress, "username") committed @gitbucket.core.helper.html.datetimeago(commit.commitTime) + @defining({ + val statuses = getStatuses(commit.id) + val (summary, summaryText) = getSummary(statuses) + (statuses, summary, summaryText) + }){ case (statuses, summaryState, summaryText) => + @if(!statuses.isEmpty){ + @helpers.commitStateIcon(summaryState) + @helpers.commitStateText(summaryState, commit.id) + — @summaryText checks + Show all checks +
+ @statuses.map{ status => +
+ @helpers.commitStateIcon(status.state) + @status.context + @status.description.map { desc => — @desc } + + @status.targetUrl.map { url => — Details } + +
+ } +
+ } + } @@ -86,5 +112,20 @@ } + } } From 5d3c5e7f3cb5070fd6a50a14ecc657c0ae1af3f3 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Sat, 12 Aug 2017 15:15:47 +0900 Subject: [PATCH 02/31] Add query string for redirect, it required by git-2.12. close #1552 --- .../core/servlet/GHCompatRepositoryAccessFilter.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala index c712dd981..0a190606c 100644 --- a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala +++ b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala @@ -23,10 +23,11 @@ class GHCompatRepositoryAccessFilter extends Filter with SystemSettingsService { val agent = request.getHeader("USER-AGENT") val response = res.asInstanceOf[HttpServletResponse] val requestPath = request.getRequestURI.substring(request.getContextPath.length) + val queryString = if (request.getQueryString != null) "?" + request.getQueryString else "" requestPath match { case githubRepositoryPattern() if agent != null && agent.toLowerCase.indexOf("git") >= 0 => - response.sendRedirect(baseUrl + "/git" + requestPath) + response.sendRedirect(baseUrl + "/git" + requestPath + queryString) case _ => chain.doFilter(req, res) } From fc28aacb52f5cbf71ec02cea1f9c4744b7207231 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Sun, 13 Aug 2017 01:59:00 +0900 Subject: [PATCH 03/31] (refs #1664)Bump to markedj 1.0.14 --- build.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index a2be14cd8..fb7d5208e 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,7 @@ libraryDependencies ++= Seq( "io.github.gitbucket" %% "scalatra-forms" % "1.1.0", "commons-io" % "commons-io" % "2.5", "io.github.gitbucket" % "solidbase" % "1.0.2", - "io.github.gitbucket" % "markedj" % "1.0.14-SNAPSHOT", + "io.github.gitbucket" % "markedj" % "1.0.14", "org.apache.commons" % "commons-compress" % "1.13", "org.apache.commons" % "commons-email" % "1.4", "org.apache.httpcomponents" % "httpclient" % "4.5.3", From 28c4ac6a1983d342c61f4c052e142386ba3acb51 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Mon, 14 Aug 2017 13:10:57 +0900 Subject: [PATCH 04/31] Add support to MIME Text part. --- .../scala/gitbucket/core/util/Notifier.scala | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/scala/gitbucket/core/util/Notifier.scala b/src/main/scala/gitbucket/core/util/Notifier.scala index 0c7d86197..4b9a57013 100644 --- a/src/main/scala/gitbucket/core/util/Notifier.scala +++ b/src/main/scala/gitbucket/core/util/Notifier.scala @@ -19,8 +19,12 @@ import SystemSettingsService.Smtp * Please see the plugin for details. */ trait Notifier { + def toNotify(subject: String, htmlMsg: String) + (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = { + toNotify(subject, htmlMsg, None)(recipients) + } - def toNotify(subject: String, msg: String) + def toNotify(subject: String, htmlMsg: String, textMsg: Option[String]) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit } @@ -35,7 +39,7 @@ object Notifier { class Mailer(private val smtp: Smtp) extends Notifier { private val logger = LoggerFactory.getLogger(classOf[Mailer]) - def toNotify(subject: String, msg: String) + def toNotify(subject: String, htmlMsg: String, textMsg: Option[String] = None) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = { context.loginAccount.foreach { loginAccount => val database = Database() @@ -43,7 +47,7 @@ class Mailer(private val smtp: Smtp) extends Notifier { val f = Future { database withSession { session => recipients(loginAccount)(session) foreach { to => - send(to, subject, msg, loginAccount) + send(to, subject, htmlMsg, loginAccount, textMsg) } } "Notifications Successful." @@ -55,7 +59,7 @@ class Mailer(private val smtp: Smtp) extends Notifier { } } - def send(to: String, subject: String, msg: String, loginAccount: Account): Unit = { + def send(to: String, subject: String, htmlMsg: String, loginAccount: Account, textMsg: Option[String] = None): Unit = { val email = new HtmlEmail email.setHostName(smtp.host) email.setSmtpPort(smtp.port.get) @@ -80,13 +84,16 @@ class Mailer(private val smtp: Smtp) extends Notifier { } email.setCharset("UTF-8") email.setSubject(subject) - email.setHtmlMsg(msg) + email.setHtmlMsg(htmlMsg) + textMsg.foreach{ msg => + email.setTextMsg(msg) + } email.addTo(to).send } } class MockMailer extends Notifier { - def toNotify(subject: String, msg: String) + def toNotify(subject: String, htmlMsg: String, textMsg: Option[String] = None) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = () } From 26e2bfbf43a95ec6be5cfb3456d4859ed12cf85c Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Mon, 14 Aug 2017 14:02:30 +0900 Subject: [PATCH 05/31] Call addedComment hook(send notification) at PR merged. --- .../gitbucket/core/controller/PullRequestsController.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala index 88328e1f2..7b9a57bfa 100644 --- a/src/main/scala/gitbucket/core/controller/PullRequestsController.scala +++ b/src/main/scala/gitbucket/core/controller/PullRequestsController.scala @@ -251,7 +251,7 @@ trait PullRequestsControllerBase extends ControllerBase { using(Git.open(getRepositoryDir(owner, name))) { git => // mark issue as merged and close. val loginAccount = context.loginAccount.get - createComment(owner, name, loginAccount.userName, issueId, form.message, "merge") + val commentId = createComment(owner, name, loginAccount.userName, issueId, form.message, "merge") createComment(owner, name, loginAccount.userName, issueId, "Close", "close") updateClosed(owner, name, issueId, true) @@ -282,7 +282,10 @@ trait PullRequestsControllerBase extends ControllerBase { callPullRequestWebHook("closed", repository, issueId, context.baseUrl, context.loginAccount.get) // call hooks - PluginRegistry().getPullRequestHooks.foreach(_.merged(issue, repository)) + PluginRegistry().getPullRequestHooks.foreach{ h => + h.addedComment(commentId, form.message, issue, repository) + h.merged(issue, repository) + } redirect(s"/${owner}/${name}/pull/${issueId}") } From 48a92df719e11fd52de46911ed294eeffe926f80 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Mon, 14 Aug 2017 18:36:34 +0900 Subject: [PATCH 06/31] Handle errors to show errors prettify and logging it. --- .../core/controller/ControllerBase.scala | 17 +++++++++++++++++ src/main/twirl/gitbucket/core/error.scala.html | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/ControllerBase.scala b/src/main/scala/gitbucket/core/controller/ControllerBase.scala index 60e7893c9..41b45cd11 100644 --- a/src/main/scala/gitbucket/core/controller/ControllerBase.scala +++ b/src/main/scala/gitbucket/core/controller/ControllerBase.scala @@ -26,6 +26,7 @@ import org.eclipse.jgit.lib.ObjectId import org.eclipse.jgit.revwalk.RevCommit import org.eclipse.jgit.treewalk._ import org.apache.commons.io.IOUtils +import org.slf4j.LoggerFactory /** * Provides generic features for controller implementations. @@ -34,6 +35,8 @@ abstract class ControllerBase extends ScalatraFilter with ClientSideValidationFormSupport with JacksonJsonSupport with I18nSupport with FlashMapSupport with Validations with SystemSettingsService { + private val logger = LoggerFactory.getLogger(getClass) + implicit val jsonFormats = gitbucket.core.api.JsonFormat.jsonFormats before("/api/v3/*") { @@ -147,6 +150,20 @@ abstract class ControllerBase extends ScalatraFilter } } + error{ + case e => { + logger.error(s"Catch unhandled error in request: ${request}", e) + if(request.hasAttribute(Keys.Request.Ajax)){ + org.scalatra.InternalServerError() + } else if(request.hasAttribute(Keys.Request.APIv3)){ + contentType = formats("json") + org.scalatra.InternalServerError(ApiError("Internal Server Error")) + } else { + org.scalatra.InternalServerError(gitbucket.core.html.error("Internal Server Error", Some(e))) + } + } + } + override def url(path: String, params: Iterable[(String, Any)] = Iterable.empty, includeContextPath: Boolean = true, includeServletPath: Boolean = true, absolutize: Boolean = true, withSessionId: Boolean = true) diff --git a/src/main/twirl/gitbucket/core/error.scala.html b/src/main/twirl/gitbucket/core/error.scala.html index 3c987d831..211073cbc 100644 --- a/src/main/twirl/gitbucket/core/error.scala.html +++ b/src/main/twirl/gitbucket/core/error.scala.html @@ -1,8 +1,18 @@ -@(title: String)(implicit context: gitbucket.core.controller.Context) +@(title: String, e: Option[Throwable]=None)(implicit context: gitbucket.core.controller.Context) @gitbucket.core.html.main("Error"){

@title

+ @e.map { ex => +

@ex.getMessage

+ + + @ex.getStackTrace.map{ st => + + } + +
@st
+ }
-} \ No newline at end of file +} From 299df34bf479485455fc43d8e25cd25d760d66cb Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Mon, 14 Aug 2017 22:12:17 +0900 Subject: [PATCH 07/31] add AdminLTE skin selection feature. --- .../controller/SystemSettingsController.scala | 3 +- .../core/service/SystemSettingsService.scala | 8 +++-- .../scala/gitbucket/core/view/helpers.scala | 6 ++++ .../gitbucket/core/admin/system.scala.html | 31 +++++++++++++++++++ src/main/twirl/gitbucket/core/main.scala.html | 4 +-- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index 784172180..54541f715 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -63,7 +63,8 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase { "tls" -> trim(label("Enable TLS", optional(boolean()))), "ssl" -> trim(label("Enable SSL", optional(boolean()))), "keystore" -> trim(label("Keystore", optional(text()))) - )(Ldap.apply)) + )(Ldap.apply)), + "skinName" -> trim(label("AdminLTE skin name", text(required))) )(SystemSettings.apply).verifying { settings => Vector( if(settings.ssh && settings.baseUrl.isEmpty){ diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index 248d12244..c73ed3591 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -54,6 +54,7 @@ trait SystemSettingsService { ldap.keystore.foreach(x => props.setProperty(LdapKeystore, x)) } } + props.setProperty(SkinName, settings.skinName.toString) using(new java.io.FileOutputStream(GitBucketConf)){ out => props.store(out, null) } @@ -111,7 +112,8 @@ trait SystemSettingsService { getOptionValue(props, LdapKeystore, None))) } else { None - } + }, + getValue(props, SkinName, "skin-blue") ) } } @@ -136,7 +138,8 @@ object SystemSettingsService { useSMTP: Boolean, smtp: Option[Smtp], ldapAuthentication: Boolean, - ldap: Option[Ldap]){ + ldap: Option[Ldap], + skinName: String){ def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/")) def sshAddress:Option[SshAddress] = @@ -219,6 +222,7 @@ object SystemSettingsService { private val LdapTls = "ldap.tls" private val LdapSsl = "ldap.ssl" private val LdapKeystore = "ldap.keystore" + private val SkinName = "skinName" private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { getSystemProperty(key).getOrElse(getEnvironmentVariable(key).getOrElse { diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index 6f38ccbe2..e926fd4ea 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -412,4 +412,10 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache */ def readableSize(size: Option[Long]): String = FileUtil.readableSize(size.getOrElse(0)) + + /** + * returns selected skin-name + */ + def skinName(implicit context: Context): String = context.settings.skinName + } diff --git a/src/main/twirl/gitbucket/core/admin/system.scala.html b/src/main/twirl/gitbucket/core/admin/system.scala.html index 4234243d9..9204e1d09 100644 --- a/src/main/twirl/gitbucket/core/admin/system.scala.html +++ b/src/main/twirl/gitbucket/core/admin/system.scala.html @@ -1,5 +1,6 @@ @(info: Option[Any])(implicit context: gitbucket.core.controller.Context) @import gitbucket.core.util.DatabaseConfig +@import gitbucket.core.view.helpers @gitbucket.core.html.main("System settings"){ @gitbucket.core.admin.html.menu("system"){ @gitbucket.core.helper.html.information(info) @@ -344,6 +345,36 @@ *@ + + + +
+ +
+ +
+ +
+
diff --git a/src/main/twirl/gitbucket/core/main.scala.html b/src/main/twirl/gitbucket/core/main.scala.html index 2324f6ec5..943b4f90e 100644 --- a/src/main/twirl/gitbucket/core/main.scala.html +++ b/src/main/twirl/gitbucket/core/main.scala.html @@ -16,7 +16,7 @@ - + @@ -42,7 +42,7 @@ } - +
Show all checks
@statuses.map{ status =>
@helpers.commitStateIcon(status.state) @status.context - @status.description.map { desc => — @desc } + @status.description.map { desc => - @desc } - @status.targetUrl.map { url => — Details } + @status.targetUrl.map { url => - Details }
} @@ -116,10 +116,9 @@ $(function () { $('.toggle-check').click(function(){ var div = $(this).next('div'); - console.log(div); if(div.is(':visible')){ $(this).text('Show all checks'); - }else{ + } else { $(this).text('Hide all checks'); } div.toggle(); From 92fea3ff0190a1f13af73fbcb10b88eaf4b96796 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Tue, 15 Aug 2017 02:44:52 +0900 Subject: [PATCH 09/31] fix test. --- .../scala/gitbucket/core/view/AvatarImageProviderSpec.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala index 27d8c7de5..ba2406945 100644 --- a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala +++ b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala @@ -118,7 +118,9 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar { useSMTP = false, smtp = None, ldapAuthentication = false, - ldap = None) + ldap = None, + skinName = "skin-blue" + ) /** * Adapter to test AvatarImageProviderImpl. From 57902af87c84c37b05f27d8ac6dd35d71591c2f4 Mon Sep 17 00:00:00 2001 From: Naoki Takezoe Date: Tue, 15 Aug 2017 02:02:17 +0900 Subject: [PATCH 10/31] (refs #1553)Fixup --- src/main/twirl/gitbucket/core/repo/commits.scala.html | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/twirl/gitbucket/core/repo/commits.scala.html b/src/main/twirl/gitbucket/core/repo/commits.scala.html index 69d72a0af..63b272c9f 100644 --- a/src/main/twirl/gitbucket/core/repo/commits.scala.html +++ b/src/main/twirl/gitbucket/core/repo/commits.scala.html @@ -70,19 +70,19 @@ val (summary, summaryText) = getSummary(statuses) (statuses, summary, summaryText) }){ case (statuses, summaryState, summaryText) => - @if(!statuses.isEmpty){ + @if(statuses.nonEmpty){ @helpers.commitStateIcon(summaryState) @helpers.commitStateText(summaryState, commit.id) - — @summaryText checks + - @summaryText checks Show all checks
@statuses.map{ status =>
@helpers.commitStateIcon(status.state) @status.context - @status.description.map { desc => — @desc } + @status.description.map { desc => - @desc } - @status.targetUrl.map { url => — Details } + @status.targetUrl.map { url => - Details }
} @@ -116,10 +116,9 @@ $(function () { $('.toggle-check').click(function(){ var div = $(this).next('div'); - console.log(div); if(div.is(':visible')){ $(this).text('Show all checks'); - }else{ + } else { $(this).text('Hide all checks'); } div.toggle(); From fdb4a6bdc6b91faf9dfa74ca2f7fb8213a5e736a Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Tue, 15 Aug 2017 03:22:25 +0900 Subject: [PATCH 11/31] change interface to textMsg: String, htmlMsg: Option[String]. SystemSettingsController calls Mailer.send directly. fix it too. --- .../controller/SystemSettingsController.scala | 5 +++-- .../scala/gitbucket/core/util/Notifier.scala | 20 +++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index 784172180..bc07e451b 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -174,8 +174,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase { post("/admin/system/sendmail", sendMailForm)(adminOnly { form => try { new Mailer(form.smtp).send(form.testAddress, - "Test message from GitBucket", "This is a test message from GitBucket.", - context.loginAccount.get) + "Test message from GitBucket", context.loginAccount.get, + "This is a test message from GitBucket.", None + ) "Test mail has been sent to: " + form.testAddress diff --git a/src/main/scala/gitbucket/core/util/Notifier.scala b/src/main/scala/gitbucket/core/util/Notifier.scala index 4b9a57013..61f3c6832 100644 --- a/src/main/scala/gitbucket/core/util/Notifier.scala +++ b/src/main/scala/gitbucket/core/util/Notifier.scala @@ -19,12 +19,12 @@ import SystemSettingsService.Smtp * Please see the plugin for details. */ trait Notifier { - def toNotify(subject: String, htmlMsg: String) + def toNotify(subject: String, textMsg: String) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = { - toNotify(subject, htmlMsg, None)(recipients) + toNotify(subject, textMsg, None)(recipients) } - def toNotify(subject: String, htmlMsg: String, textMsg: Option[String]) + def toNotify(subject: String, textMsg: String, htmlMsg: Option[String]) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit } @@ -39,7 +39,7 @@ object Notifier { class Mailer(private val smtp: Smtp) extends Notifier { private val logger = LoggerFactory.getLogger(classOf[Mailer]) - def toNotify(subject: String, htmlMsg: String, textMsg: Option[String] = None) + def toNotify(subject: String, textMsg: String, htmlMsg: Option[String] = None) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = { context.loginAccount.foreach { loginAccount => val database = Database() @@ -47,7 +47,7 @@ class Mailer(private val smtp: Smtp) extends Notifier { val f = Future { database withSession { session => recipients(loginAccount)(session) foreach { to => - send(to, subject, htmlMsg, loginAccount, textMsg) + send(to, subject, loginAccount, textMsg, htmlMsg) } } "Notifications Successful." @@ -59,7 +59,7 @@ class Mailer(private val smtp: Smtp) extends Notifier { } } - def send(to: String, subject: String, htmlMsg: String, loginAccount: Account, textMsg: Option[String] = None): Unit = { + def send(to: String, subject: String, loginAccount: Account, textMsg: String, htmlMsg: Option[String] = None): Unit = { val email = new HtmlEmail email.setHostName(smtp.host) email.setSmtpPort(smtp.port.get) @@ -84,9 +84,9 @@ class Mailer(private val smtp: Smtp) extends Notifier { } email.setCharset("UTF-8") email.setSubject(subject) - email.setHtmlMsg(htmlMsg) - textMsg.foreach{ msg => - email.setTextMsg(msg) + email.setTextMsg(textMsg) + htmlMsg.foreach { msg => + email.setHtmlMsg(msg) } email.addTo(to).send @@ -94,6 +94,6 @@ class Mailer(private val smtp: Smtp) extends Notifier { } class MockMailer extends Notifier { - def toNotify(subject: String, htmlMsg: String, textMsg: Option[String] = None) + def toNotify(subject: String, textMsg: String, htmlMsg: Option[String] = None) (recipients: Account => Session => Seq[String])(implicit context: Context): Unit = () } From 772ac80764e1d2a0f39d02f76125f316e3b79cac Mon Sep 17 00:00:00 2001 From: Hidetake Iwata Date: Wed, 16 Aug 2017 00:19:12 +0900 Subject: [PATCH 12/31] Improve GitHub compatible URL --- .../GHCompatRepositoryAccessFilter.scala | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala index 0a190606c..7fa5fc9aa 100644 --- a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala +++ b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala @@ -4,35 +4,33 @@ import javax.servlet._ import javax.servlet.http.{HttpServletRequest, HttpServletResponse} import gitbucket.core.service.SystemSettingsService +import gitbucket.core.util.Implicits._ /** * A controller to provide GitHub compatible URL for Git clients. */ class GHCompatRepositoryAccessFilter extends Filter with SystemSettingsService { - /** - * Pattern of GitHub compatible repository URL. - * /:user/:repo.git/ - */ - private val githubRepositoryPattern = """^/[^/]+/[^/]+\.git/.*""".r + override def init(filterConfig: FilterConfig): Unit = {} - override def init(filterConfig: FilterConfig) = {} + override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain): Unit = { + val request = req.asInstanceOf[HttpServletRequest] + request.paths match { + // baseUrl/repositoryOwner/repositoryName/info/refs + // baseUrl/repositoryOwner/repositoryName.git/info/refs + case Array(repositoryOwner, repositoryName, "info", "refs", _*) => redirectToGitServlet(req, res) - override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) = { - implicit val request = req.asInstanceOf[HttpServletRequest] - val agent = request.getHeader("USER-AGENT") - val response = res.asInstanceOf[HttpServletResponse] - val requestPath = request.getRequestURI.substring(request.getContextPath.length) - val queryString = if (request.getQueryString != null) "?" + request.getQueryString else "" - - requestPath match { - case githubRepositoryPattern() if agent != null && agent.toLowerCase.indexOf("git") >= 0 => - response.sendRedirect(baseUrl + "/git" + requestPath + queryString) - case _ => - chain.doFilter(req, res) + case _ => chain.doFilter(req, res) } } - override def destroy() = {} + private def redirectToGitServlet(req: ServletRequest, res: ServletResponse): Unit = { + val request = req.asInstanceOf[HttpServletRequest] + val response = res.asInstanceOf[HttpServletResponse] + val query = Option(request.getQueryString).map("?" + _).getOrElse("") + response.sendRedirect(baseUrl(request) + "/git" + request.getRequestURI + query) + } + + override def destroy(): Unit = {} } From 040d812f2a862b48165187a61db2839d0909af58 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Thu, 17 Aug 2017 17:48:53 +0900 Subject: [PATCH 13/31] add debug option to SystemSettings. and error page shows stacktrace only for admin or debug settings. --- .../controller/SystemSettingsController.scala | 5 +++-- .../core/service/SystemSettingsService.scala | 8 +++++-- .../twirl/gitbucket/core/error.scala.html | 22 +++++++++++-------- .../core/view/AvatarImageProviderSpec.scala | 3 ++- 4 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index 784172180..2e54423f6 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -62,8 +62,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase { "mailAttribute" -> trim(label("Mail address attribute", optional(text()))), "tls" -> trim(label("Enable TLS", optional(boolean()))), "ssl" -> trim(label("Enable SSL", optional(boolean()))), - "keystore" -> trim(label("Keystore", optional(text()))) - )(Ldap.apply)) + "keystore" -> trim(label("Keystore", optional(text()))), + )(Ldap.apply)), + "debug" -> trim(label("Debug", boolean())) )(SystemSettings.apply).verifying { settings => Vector( if(settings.ssh && settings.baseUrl.isEmpty){ diff --git a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala index 248d12244..7734f3e8a 100644 --- a/src/main/scala/gitbucket/core/service/SystemSettingsService.scala +++ b/src/main/scala/gitbucket/core/service/SystemSettingsService.scala @@ -54,6 +54,7 @@ trait SystemSettingsService { ldap.keystore.foreach(x => props.setProperty(LdapKeystore, x)) } } + props.setProperty(Debug, settings.debug.toString) using(new java.io.FileOutputStream(GitBucketConf)){ out => props.store(out, null) } @@ -111,7 +112,8 @@ trait SystemSettingsService { getOptionValue(props, LdapKeystore, None))) } else { None - } + }, + getValue(props, Debug, false) ) } } @@ -136,7 +138,8 @@ object SystemSettingsService { useSMTP: Boolean, smtp: Option[Smtp], ldapAuthentication: Boolean, - ldap: Option[Ldap]){ + ldap: Option[Ldap], + debug: Boolean){ def baseUrl(request: HttpServletRequest): String = baseUrl.fold(request.baseUrl)(_.stripSuffix("/")) def sshAddress:Option[SshAddress] = @@ -219,6 +222,7 @@ object SystemSettingsService { private val LdapTls = "ldap.tls" private val LdapSsl = "ldap.ssl" private val LdapKeystore = "ldap.keystore" + private val Debug = "debug" private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { getSystemProperty(key).getOrElse(getEnvironmentVariable(key).getOrElse { diff --git a/src/main/twirl/gitbucket/core/error.scala.html b/src/main/twirl/gitbucket/core/error.scala.html index 211073cbc..267179705 100644 --- a/src/main/twirl/gitbucket/core/error.scala.html +++ b/src/main/twirl/gitbucket/core/error.scala.html @@ -3,15 +3,19 @@

@title

- @e.map { ex => -

@ex.getMessage

- - - @ex.getStackTrace.map{ st => - - } - -
@st
+ @if(context.loginAccount.map{_.isAdmin}.getOrElse(false) || context.settings.debug){ + @e.map { ex => +

@ex.getMessage

+ + + @ex.getStackTrace.map{ st => + + } + +
@st
+ } + } else { +
Please contact your administrator.
}
diff --git a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala index 27d8c7de5..c78b205ed 100644 --- a/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala +++ b/src/test/scala/gitbucket/core/view/AvatarImageProviderSpec.scala @@ -118,7 +118,8 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar { useSMTP = false, smtp = None, ldapAuthentication = false, - ldap = None) + ldap = None, + debug = false) /** * Adapter to test AvatarImageProviderImpl. From a6cb71f9c3fab2bfeba7e50a492f682b0b3d7960 Mon Sep 17 00:00:00 2001 From: KOUNOIKE Yuusuke Date: Fri, 18 Aug 2017 01:55:56 +0900 Subject: [PATCH 14/31] remove helpers.skinName. (by review comment) --- src/main/scala/gitbucket/core/view/helpers.scala | 6 ------ src/main/twirl/gitbucket/core/admin/system.scala.html | 2 +- src/main/twirl/gitbucket/core/main.scala.html | 4 ++-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/scala/gitbucket/core/view/helpers.scala b/src/main/scala/gitbucket/core/view/helpers.scala index e926fd4ea..6f38ccbe2 100644 --- a/src/main/scala/gitbucket/core/view/helpers.scala +++ b/src/main/scala/gitbucket/core/view/helpers.scala @@ -412,10 +412,4 @@ object helpers extends AvatarImageProvider with LinkConverter with RequestCache */ def readableSize(size: Option[Long]): String = FileUtil.readableSize(size.getOrElse(0)) - - /** - * returns selected skin-name - */ - def skinName(implicit context: Context): String = context.settings.skinName - } diff --git a/src/main/twirl/gitbucket/core/admin/system.scala.html b/src/main/twirl/gitbucket/core/admin/system.scala.html index 9204e1d09..4496e65f9 100644 --- a/src/main/twirl/gitbucket/core/admin/system.scala.html +++ b/src/main/twirl/gitbucket/core/admin/system.scala.html @@ -370,7 +370,7 @@ "skin-yellow", "skin-yellow-light", ).map{ skin => - + }
diff --git a/src/main/twirl/gitbucket/core/main.scala.html b/src/main/twirl/gitbucket/core/main.scala.html index 943b4f90e..612491a83 100644 --- a/src/main/twirl/gitbucket/core/main.scala.html +++ b/src/main/twirl/gitbucket/core/main.scala.html @@ -16,7 +16,7 @@ - + @@ -42,7 +42,7 @@ } - +