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:
- External URL:
+ External URL:
+ (Put if you have the external issue tracking system for this project)
+
@@ -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:
- External URL:
+
+
+ Allow read-only users to edit Wiki pages
+
+ External URL:
+ (Put if you have the external Wiki for this project)
+
@@ -89,6 +95,7 @@
function updateFeatures() {
$('#externalIssuesUrl').prop('disabled', $('#enableIssues').prop('checked'));
+ $('#allowWikiEditing').prop('disabled', !$('#enableWiki').prop('checked'));
$('#externalWikiUrl').prop('disabled', $('#enableWiki').prop('checked'));
}