diff --git a/src/main/resources/update/gitbucket-core_4.2.xml b/src/main/resources/update/gitbucket-core_4.2.xml index b4ad19c..78aa748 100644 --- a/src/main/resources/update/gitbucket-core_4.2.xml +++ b/src/main/resources/update/gitbucket-core_4.2.xml @@ -2,8 +2,9 @@ - + + diff --git a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala index fd32311..b60ae5d 100644 --- a/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositorySettingsController.scala @@ -32,8 +32,9 @@ description: Option[String], isPrivate: Boolean, enableIssues: Boolean, - enableWiki: Boolean, externalIssuesUrl: Option[String], + enableWiki: Boolean, + allowWikiEditing: Boolean, externalWikiUrl: Option[String] ) @@ -42,8 +43,9 @@ "description" -> trim(label("Description" , optional(text()))), "isPrivate" -> trim(label("Repository Type" , boolean())), "enableIssues" -> trim(label("Enable Issues" , boolean())), - "enableWiki" -> trim(label("Enable Wiki" , boolean())), "externalIssuesUrl" -> trim(label("External Issues URL", optional(text(maxlength(200))))), + "enableWiki" -> trim(label("Enable Wiki" , boolean())), + "allowWikiEditing" -> trim(label("Allow Wiki Editing" , boolean())), "externalWikiUrl" -> trim(label("External Wiki URL" , optional(text(maxlength(200))))) )(OptionsForm.apply) @@ -106,8 +108,9 @@ repository.repository.isPrivate } getOrElse form.isPrivate, form.enableIssues, - form.enableWiki, form.externalIssuesUrl, + form.enableWiki, + form.allowWikiEditing, form.externalWikiUrl ) // Change repository name diff --git a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala index b1fa0f9..12ee473 100644 --- a/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala +++ b/src/main/scala/gitbucket/core/controller/RepositoryViewerController.scala @@ -691,8 +691,6 @@ private def isEditable(owner: String, repository: String, author: String)(implicit context: Context): Boolean = hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName - - override protected def renderUncaughtException(e: Throwable)(implicit request: HttpServletRequest, response: HttpServletResponse): Unit = { e.printStackTrace() } diff --git a/src/main/scala/gitbucket/core/controller/WikiController.scala b/src/main/scala/gitbucket/core/controller/WikiController.scala index 49fb2e2..ad98cee 100644 --- a/src/main/scala/gitbucket/core/controller/WikiController.scala +++ b/src/main/scala/gitbucket/core/controller/WikiController.scala @@ -1,7 +1,8 @@ package gitbucket.core.controller +import gitbucket.core.service.RepositoryService.RepositoryInfo import gitbucket.core.wiki.html -import gitbucket.core.service.{RepositoryService, WikiService, ActivityService, AccountService} +import gitbucket.core.service.{AccountService, ActivityService, RepositoryService, WikiService} import gitbucket.core.util._ import gitbucket.core.util.StringUtil._ import gitbucket.core.util.ControlUtil._ @@ -39,7 +40,7 @@ get("/:owner/:repository/wiki")(referrersOnly { repository => getWikiPage(repository.owner, repository.name, "Home").map { page => html.page("Home", page, getWikiPageList(repository.owner, repository.name), - repository, hasWritePermission(repository.owner, repository.name, context.loginAccount), + repository, isEditable(repository), getWikiPage(repository.owner, repository.name, "_Sidebar"), getWikiPage(repository.owner, repository.name, "_Footer")) } getOrElse redirect(s"/${repository.owner}/${repository.name}/wiki/Home/_edit") @@ -50,7 +51,7 @@ getWikiPage(repository.owner, repository.name, pageName).map { page => html.page(pageName, page, getWikiPageList(repository.owner, repository.name), - repository, hasWritePermission(repository.owner, repository.name, context.loginAccount), + repository, isEditable(repository), getWikiPage(repository.owner, repository.name, "_Sidebar"), getWikiPage(repository.owner, repository.name, "_Footer")) } getOrElse redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_edit") @@ -62,7 +63,7 @@ using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => JGitUtil.getCommitLog(git, "master", path = pageName + ".md") match { case Right((logs, hasNext)) => html.history(Some(pageName), logs, repository) - case Left(_) => NotFound + case Left(_) => NotFound() } } }) @@ -73,7 +74,7 @@ using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => html.compare(Some(pageName), from, to, JGitUtil.getDiffs(git, from, to, true).filter(_.newPath == pageName + ".md"), repository, - hasWritePermission(repository.owner, repository.name, context.loginAccount), flash.get("info")) + isEditable(repository), flash.get("info")) } }) @@ -82,102 +83,115 @@ using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => html.compare(None, from, to, JGitUtil.getDiffs(git, from, to, true), repository, - hasWritePermission(repository.owner, repository.name, context.loginAccount), flash.get("info")) + isEditable(repository), flash.get("info")) } }) - get("/:owner/:repository/wiki/:page/_revert/:commitId")(collaboratorsOnly { repository => - val pageName = StringUtil.urlDecode(params("page")) - val Array(from, to) = params("commitId").split("\\.\\.\\.") + get("/:owner/:repository/wiki/:page/_revert/:commitId")(referrersOnly { repository => + if(isEditable(repository)){ + val pageName = StringUtil.urlDecode(params("page")) + val Array(from, to) = params("commitId").split("\\.\\.\\.") - if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, Some(pageName))){ - redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}") - } else { - flash += "info" -> "This patch was not able to be reversed." - redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_compare/${from}...${to}") - } - }) - - get("/:owner/:repository/wiki/_revert/:commitId")(collaboratorsOnly { repository => - val Array(from, to) = params("commitId").split("\\.\\.\\.") - - if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, None)){ - redirect(s"/${repository.owner}/${repository.name}/wiki/") - } else { - flash += "info" -> "This patch was not able to be reversed." - redirect(s"/${repository.owner}/${repository.name}/wiki/_compare/${from}...${to}") - } - }) - - get("/:owner/:repository/wiki/:page/_edit")(collaboratorsOnly { repository => - val pageName = StringUtil.urlDecode(params("page")) - html.edit(pageName, getWikiPage(repository.owner, repository.name, pageName), repository) - }) - - post("/:owner/:repository/wiki/_edit", editForm)(collaboratorsOnly { (form, repository) => - defining(context.loginAccount.get){ loginAccount => - saveWikiPage( - repository.owner, - repository.name, - form.currentPageName, - form.pageName, - appendNewLine(convertLineSeparator(form.content, "LF"), "LF"), - loginAccount, - form.message.getOrElse(""), - Some(form.id) - ).map { commitId => - updateLastActivityDate(repository.owner, repository.name) - recordEditWikiPageActivity(repository.owner, repository.name, loginAccount.userName, form.pageName, commitId) - } - if(notReservedPageName(form.pageName)) { - redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(form.pageName)}") + if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, Some(pageName))){ + redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}") } else { - redirect(s"/${repository.owner}/${repository.name}/wiki") + flash += "info" -> "This patch was not able to be reversed." + redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_compare/${from}...${to}") } - } + } else Unauthorized() + }) + + get("/:owner/:repository/wiki/_revert/:commitId")(referrersOnly { repository => + if(isEditable(repository)){ + val Array(from, to) = params("commitId").split("\\.\\.\\.") + + if(revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, None)){ + redirect(s"/${repository.owner}/${repository.name}/wiki/") + } else { + flash += "info" -> "This patch was not able to be reversed." + redirect(s"/${repository.owner}/${repository.name}/wiki/_compare/${from}...${to}") + } + } else Unauthorized() + }) + + get("/:owner/:repository/wiki/:page/_edit")(referrersOnly { repository => + if(isEditable(repository)){ + val pageName = StringUtil.urlDecode(params("page")) + html.edit(pageName, getWikiPage(repository.owner, repository.name, pageName), repository) + } else Unauthorized() }) - get("/:owner/:repository/wiki/_new")(collaboratorsOnly { - html.edit("", None, _) + post("/:owner/:repository/wiki/_edit", editForm)(referrersOnly { (form, repository) => + if(isEditable(repository)){ + defining(context.loginAccount.get){ loginAccount => + saveWikiPage( + repository.owner, + repository.name, + form.currentPageName, + form.pageName, + appendNewLine(convertLineSeparator(form.content, "LF"), "LF"), + loginAccount, + form.message.getOrElse(""), + Some(form.id) + ).map { commitId => + updateLastActivityDate(repository.owner, repository.name) + recordEditWikiPageActivity(repository.owner, repository.name, loginAccount.userName, form.pageName, commitId) + } + if(notReservedPageName(form.pageName)) { + redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(form.pageName)}") + } else { + redirect(s"/${repository.owner}/${repository.name}/wiki") + } + } + } else Unauthorized() }) - post("/:owner/:repository/wiki/_new", newForm)(collaboratorsOnly { (form, repository) => - defining(context.loginAccount.get){ loginAccount => - saveWikiPage(repository.owner, repository.name, form.currentPageName, form.pageName, + get("/:owner/:repository/wiki/_new")(referrersOnly { repository => + if(isEditable(repository)){ + html.edit("", None, repository) + } else Unauthorized() + }) + + post("/:owner/:repository/wiki/_new", newForm)(referrersOnly { (form, repository) => + if(isEditable(repository)){ + defining(context.loginAccount.get){ loginAccount => + saveWikiPage(repository.owner, repository.name, form.currentPageName, form.pageName, form.content, loginAccount, form.message.getOrElse(""), None) - updateLastActivityDate(repository.owner, repository.name) - recordCreateWikiPageActivity(repository.owner, repository.name, loginAccount.userName, form.pageName) + updateLastActivityDate(repository.owner, repository.name) + recordCreateWikiPageActivity(repository.owner, repository.name, loginAccount.userName, form.pageName) - if(notReservedPageName(form.pageName)) { - redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(form.pageName)}") - } else { - redirect(s"/${repository.owner}/${repository.name}/wiki") + if(notReservedPageName(form.pageName)) { + redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(form.pageName)}") + } else { + redirect(s"/${repository.owner}/${repository.name}/wiki") + } } - } + } else Unauthorized() }) - get("/:owner/:repository/wiki/:page/_delete")(collaboratorsOnly { repository => - val pageName = StringUtil.urlDecode(params("page")) + get("/:owner/:repository/wiki/:page/_delete")(referrersOnly { repository => + if(isEditable(repository)){ + val pageName = StringUtil.urlDecode(params("page")) - defining(context.loginAccount.get){ loginAccount => - deleteWikiPage(repository.owner, repository.name, pageName, loginAccount.fullName, loginAccount.mailAddress, s"Destroyed ${pageName}") - updateLastActivityDate(repository.owner, repository.name) + defining(context.loginAccount.get){ loginAccount => + deleteWikiPage(repository.owner, repository.name, pageName, loginAccount.fullName, loginAccount.mailAddress, s"Destroyed ${pageName}") + updateLastActivityDate(repository.owner, repository.name) - redirect(s"/${repository.owner}/${repository.name}/wiki") - } + redirect(s"/${repository.owner}/${repository.name}/wiki") + } + } else Unauthorized() }) get("/:owner/:repository/wiki/_pages")(referrersOnly { repository => - html.pages(getWikiPageList(repository.owner, repository.name), repository, - hasWritePermission(repository.owner, repository.name, context.loginAccount)) + html.pages(getWikiPageList(repository.owner, repository.name), repository, isEditable(repository)) }) get("/:owner/:repository/wiki/_history")(referrersOnly { repository => using(Git.open(getWikiRepositoryDir(repository.owner, repository.name))){ git => JGitUtil.getCommitLog(git, "master") match { case Right((logs, hasNext)) => html.history(None, logs, repository) - case Left(_) => NotFound + case Left(_) => NotFound() } } }) @@ -226,4 +240,9 @@ private def targetWikiPage = getWikiPage(params("owner"), params("repository"), params("pageName")) + private def isEditable(repository: RepositoryInfo)(implicit context: Context): Boolean = + repository.repository.allowWikiEditing || ( + hasWritePermission(repository.owner, repository.name, context.loginAccount) + ) + } diff --git a/src/main/scala/gitbucket/core/model/Repository.scala b/src/main/scala/gitbucket/core/model/Repository.scala index f4e8138..ebdfb3a 100644 --- a/src/main/scala/gitbucket/core/model/Repository.scala +++ b/src/main/scala/gitbucket/core/model/Repository.scala @@ -18,10 +18,13 @@ val parentUserName = column[String]("PARENT_USER_NAME") val parentRepositoryName = column[String]("PARENT_REPOSITORY_NAME") val enableIssues = column[Boolean]("ENABLE_ISSUES") - val enableWiki = column[Boolean]("ENABLE_WIKI") val externalIssuesUrl = column[String]("EXTERNAL_ISSUES_URL") + val enableWiki = column[Boolean]("ENABLE_WIKI") + val allowWikiEditing = column[Boolean]("ALLOW_WIKI_EDITING") val externalWikiUrl = column[String]("EXTERNAL_WIKI_URL") - def * = (userName, repositoryName, isPrivate, description.?, defaultBranch, registeredDate, updatedDate, lastActivityDate, originUserName.?, originRepositoryName.?, parentUserName.?, parentRepositoryName.?, enableIssues, enableWiki, externalIssuesUrl.?, externalWikiUrl.?) <> (Repository.tupled, Repository.unapply) + def * = (userName, repositoryName, isPrivate, description.?, defaultBranch, + registeredDate, updatedDate, lastActivityDate, originUserName.?, originRepositoryName.?, parentUserName.?, parentRepositoryName.?, + enableIssues, externalIssuesUrl.?, enableWiki, allowWikiEditing, externalWikiUrl.?) <> (Repository.tupled, Repository.unapply) def byPrimaryKey(owner: String, repository: String) = byRepository(owner, repository) } @@ -41,7 +44,8 @@ parentUserName: Option[String], parentRepositoryName: Option[String], enableIssues: Boolean, - enableWiki: Boolean, externalIssuesUrl: Option[String], + enableWiki: Boolean, + allowWikiEditing: Boolean, externalWikiUrl: Option[String] ) diff --git a/src/main/scala/gitbucket/core/service/RepositoryService.scala b/src/main/scala/gitbucket/core/service/RepositoryService.scala index 15dce71..7167b37 100644 --- a/src/main/scala/gitbucket/core/service/RepositoryService.scala +++ b/src/main/scala/gitbucket/core/service/RepositoryService.scala @@ -38,8 +38,9 @@ parentUserName = parentUserName, parentRepositoryName = parentRepositoryName, enableIssues = true, - enableWiki = true, externalIssuesUrl = None, + enableWiki = true, + allowWikiEditing = true, externalWikiUrl = None ) @@ -319,10 +320,11 @@ */ def saveRepositoryOptions(userName: String, repositoryName: String, description: Option[String], isPrivate: Boolean, - enableIssues: Boolean, enableWiki: Boolean, externalIssuesUrl: Option[String], externalWikiUrl: Option[String])(implicit s: Session): Unit = + enableIssues: Boolean, externalIssuesUrl: Option[String], + enableWiki: Boolean, allowWikiEditing: Boolean, externalWikiUrl: Option[String])(implicit s: Session): Unit = Repositories.filter(_.byRepository(userName, repositoryName)) - .map { r => (r.description.?, r.isPrivate, r.enableIssues, r.enableWiki, r.externalIssuesUrl.?, r.externalWikiUrl.?, r.updatedDate) } - .update (description, isPrivate, enableIssues, enableWiki, externalIssuesUrl, externalWikiUrl, currentDate) + .map { r => (r.description.?, r.isPrivate, r.enableIssues, r.externalIssuesUrl.?, r.enableWiki, r.allowWikiEditing, r.externalWikiUrl.?, r.updatedDate) } + .update (description, isPrivate, enableIssues, externalIssuesUrl, enableWiki, allowWikiEditing, externalWikiUrl, currentDate) def saveRepositoryDefaultBranch(userName: String, repositoryName: String, defaultBranch: String)(implicit s: Session): Unit = diff --git a/src/main/twirl/gitbucket/core/settings/options.scala.html b/src/main/twirl/gitbucket/core/settings/options.scala.html index cdce8ce..2d5856e 100644 --- a/src/main/twirl/gitbucket/core/settings/options.scala.html +++ b/src/main/twirl/gitbucket/core/settings/options.scala.html @@ -51,10 +51,11 @@ Issues
Provides Lightweight issue tracking integrated with this repository. Add issues to milestones, label issues, and close & reference issues from commit messages. - If you use external issue tracking system, turn off the checkbox above and put that URL into the following box:
- +
@@ -63,10 +64,15 @@ Wiki
Provides a simple solution to manage documents. All users who can look this repository can read and collaborators can edit pages. - If you have documents at the outside of GitBucket, turn off the checkbox above and put that URL into the following box:
- + +
@@ -89,6 +95,7 @@ function updateFeatures() { $('#externalIssuesUrl').prop('disabled', $('#enableIssues').prop('checked')); + $('#allowWikiEditing').prop('disabled', !$('#enableWiki').prop('checked')); $('#externalWikiUrl').prop('disabled', $('#enableWiki').prop('checked')); }