Eliminate context.loginAccount.get() by adding context.withLoginAccount() (#2729)

This commit is contained in:
Naoki Takezoe
2021-04-07 12:19:47 +09:00
committed by GitHub
parent cbdc0528ca
commit 9f7048a19c
11 changed files with 962 additions and 821 deletions

View File

@@ -629,7 +629,9 @@ trait AccountControllerBase extends AccountManagementControllerBase {
} }
get("/groups/new")(usersOnly { get("/groups/new")(usersOnly {
html.creategroup(List(GroupMember("", context.loginAccount.get.userName, true))) context.withLoginAccount { loginAccount =>
html.creategroup(List(GroupMember("", loginAccount.userName, true)))
}
}) })
post("/groups/new", newGroupForm)(usersOnly { form => post("/groups/new", newGroupForm)(usersOnly { form =>
@@ -716,83 +718,92 @@ trait AccountControllerBase extends AccountManagementControllerBase {
* Show the new repository form. * Show the new repository form.
*/ */
get("/new")(usersOnly { get("/new")(usersOnly {
html.newrepo(getGroupsByUserName(context.loginAccount.get.userName), context.settings.isCreateRepoOptionPublic) context.withLoginAccount { loginAccount =>
html.newrepo(getGroupsByUserName(loginAccount.userName), context.settings.isCreateRepoOptionPublic)
}
}) })
/** /**
* Create new repository. * Create new repository.
*/ */
post("/new", newRepositoryForm)(usersOnly { form => post("/new", newRepositoryForm)(usersOnly { form =>
if (context.settings.repositoryOperation.create || context.loginAccount.get.isAdmin) { context.withLoginAccount {
LockUtil.lock(s"${form.owner}/${form.name}") { loginAccount =>
if (getRepository(form.owner, form.name).isDefined) { if (context.settings.repositoryOperation.create || loginAccount.isAdmin) {
// redirect to the repository if repository already exists LockUtil.lock(s"${form.owner}/${form.name}") {
redirect(s"/${form.owner}/${form.name}") if (getRepository(form.owner, form.name).isDefined) {
} else if (!canCreateRepository(form.owner, context.loginAccount.get)) { // redirect to the repository if repository already exists
// Permission error redirect(s"/${form.owner}/${form.name}")
Forbidden() } else if (!canCreateRepository(form.owner, loginAccount)) {
} else { // Permission error
// create repository asynchronously Forbidden()
createRepository( } else {
context.loginAccount.get, // create repository asynchronously
form.owner, createRepository(
form.name, loginAccount,
form.description, form.owner,
form.isPrivate, form.name,
form.initOption, form.description,
form.sourceUrl form.isPrivate,
) form.initOption,
// redirect to the repository form.sourceUrl
redirect(s"/${form.owner}/${form.name}") )
} // redirect to the repository
} redirect(s"/${form.owner}/${form.name}")
} else Forbidden() }
}
} else Forbidden()
}
}) })
get("/:owner/:repository/fork")(readableUsersOnly { repository => get("/:owner/:repository/fork")(readableUsersOnly { repository =>
val loginAccount = context.loginAccount.get context.withLoginAccount {
if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) { loginAccount =>
val loginUserName = loginAccount.userName if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) {
val groups = getGroupsByUserName(loginUserName) val loginUserName = loginAccount.userName
groups match { val groups = getGroupsByUserName(loginUserName)
case _: List[String] => groups match {
val managerPermissions = groups.map { group => case _: List[String] =>
val members = getGroupMembers(group) val managerPermissions = groups.map { group =>
context.loginAccount.exists( val members = getGroupMembers(group)
x => context.loginAccount.exists(
members.exists { member => x =>
member.userName == x.userName && member.isManager members.exists { member =>
member.userName == x.userName && member.isManager
}
)
} }
) helper.html.forkrepository(
repository,
(groups zip managerPermissions).sortBy(_._1)
)
case _ => redirect(s"/${loginUserName}")
} }
helper.html.forkrepository( } else BadRequest()
repository, }
(groups zip managerPermissions).sortBy(_._1)
)
case _ => redirect(s"/${loginUserName}")
}
} else BadRequest()
}) })
post("/:owner/:repository/fork", accountForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/fork", accountForm)(readableUsersOnly { (form, repository) =>
val loginAccount = context.loginAccount.get context.withLoginAccount {
if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) { loginAccount =>
val loginUserName = loginAccount.userName if (repository.repository.options.allowFork && (context.settings.repositoryOperation.fork || loginAccount.isAdmin)) {
val accountName = form.accountName val loginUserName = loginAccount.userName
val accountName = form.accountName
if (getRepository(accountName, repository.name).isDefined) { if (getRepository(accountName, repository.name).isDefined) {
// redirect to the repository if repository already exists // redirect to the repository if repository already exists
redirect(s"/${accountName}/${repository.name}") redirect(s"/${accountName}/${repository.name}")
} else if (!canCreateRepository(accountName, loginAccount)) { } else if (!canCreateRepository(accountName, loginAccount)) {
// Permission error // Permission error
Forbidden() Forbidden()
} else { } else {
// fork repository asynchronously // fork repository asynchronously
forkRepository(accountName, repository, loginUserName) forkRepository(accountName, repository, loginUserName)
// redirect to the repository // redirect to the repository
redirect(s"/${accountName}/${repository.name}") redirect(s"/${accountName}/${repository.name}")
} }
} else Forbidden() } else Forbidden()
}
}) })
private def existsAccount: Constraint = new Constraint() { private def existsAccount: Constraint = new Constraint() {

View File

@@ -303,6 +303,13 @@ case class Context(
} }
val sidebarCollapse = request.getSession.getAttribute("sidebar-collapse") != null val sidebarCollapse = request.getSession.getAttribute("sidebar-collapse") != null
def withLoginAccount(f: Account => Any): Any = {
loginAccount match {
case Some(loginAccount) => f(loginAccount)
case None => Unauthorized()
}
}
/** /**
* Get object from cache. * Get object from cache.
* *

View File

@@ -1,6 +1,7 @@
package gitbucket.core.controller package gitbucket.core.controller
import gitbucket.core.dashboard.html import gitbucket.core.dashboard.html
import gitbucket.core.model.Account
import gitbucket.core.service._ import gitbucket.core.service._
import gitbucket.core.util.{Keys, UsersAuthenticator} import gitbucket.core.util.{Keys, UsersAuthenticator}
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
@@ -34,45 +35,63 @@ trait DashboardControllerBase extends ControllerBase {
with UsersAuthenticator => with UsersAuthenticator =>
get("/dashboard/repos")(usersOnly { get("/dashboard/repos")(usersOnly {
val repos = getVisibleRepositories( context.withLoginAccount { loginAccount =>
context.loginAccount, val repos = getVisibleRepositories(
None, context.loginAccount,
withoutPhysicalInfo = true, None,
limit = context.settings.limitVisibleRepositories withoutPhysicalInfo = true,
) limit = context.settings.limitVisibleRepositories
html.repos(getGroupNames(context.loginAccount.get.userName), repos, repos) )
html.repos(getGroupNames(loginAccount.userName), repos, repos)
}
}) })
get("/dashboard/issues")(usersOnly { get("/dashboard/issues")(usersOnly {
searchIssues("created_by") context.withLoginAccount { loginAccount =>
searchIssues(loginAccount, "created_by")
}
}) })
get("/dashboard/issues/assigned")(usersOnly { get("/dashboard/issues/assigned")(usersOnly {
searchIssues("assigned") context.withLoginAccount { loginAccount =>
searchIssues(loginAccount, "assigned")
}
}) })
get("/dashboard/issues/created_by")(usersOnly { get("/dashboard/issues/created_by")(usersOnly {
searchIssues("created_by") context.withLoginAccount { loginAccount =>
searchIssues(loginAccount, "created_by")
}
}) })
get("/dashboard/issues/mentioned")(usersOnly { get("/dashboard/issues/mentioned")(usersOnly {
searchIssues("mentioned") context.withLoginAccount { loginAccount =>
searchIssues(loginAccount, "mentioned")
}
}) })
get("/dashboard/pulls")(usersOnly { get("/dashboard/pulls")(usersOnly {
searchPullRequests("created_by") context.withLoginAccount { loginAccount =>
searchPullRequests(loginAccount, "created_by")
}
}) })
get("/dashboard/pulls/created_by")(usersOnly { get("/dashboard/pulls/created_by")(usersOnly {
searchPullRequests("created_by") context.withLoginAccount { loginAccount =>
searchPullRequests(loginAccount, "created_by")
}
}) })
get("/dashboard/pulls/assigned")(usersOnly { get("/dashboard/pulls/assigned")(usersOnly {
searchPullRequests("assigned") context.withLoginAccount { loginAccount =>
searchPullRequests(loginAccount, "assigned")
}
}) })
get("/dashboard/pulls/mentioned")(usersOnly { get("/dashboard/pulls/mentioned")(usersOnly {
searchPullRequests("mentioned") context.withLoginAccount { loginAccount =>
searchPullRequests(loginAccount, "mentioned")
}
}) })
private def getOrCreateCondition(key: String, filter: String, userName: String) = { private def getOrCreateCondition(key: String, filter: String, userName: String) = {
@@ -85,10 +104,10 @@ trait DashboardControllerBase extends ControllerBase {
} }
} }
private def searchIssues(filter: String) = { private def searchIssues(loginAccount: Account, filter: String) = {
import IssuesService._ import IssuesService._
val userName = context.loginAccount.get.userName val userName = loginAccount.userName
val condition = getOrCreateCondition(Keys.Session.DashboardIssues, filter, userName) val condition = getOrCreateCondition(Keys.Session.DashboardIssues, filter, userName)
val userRepos = getUserRepositories(userName, true).map(repo => repo.owner -> repo.name) val userRepos = getUserRepositories(userName, true).map(repo => repo.owner -> repo.name)
val page = IssueSearchCondition.page(request) val page = IssueSearchCondition.page(request)
@@ -115,11 +134,11 @@ trait DashboardControllerBase extends ControllerBase {
) )
} }
private def searchPullRequests(filter: String) = { private def searchPullRequests(loginAccount: Account, filter: String) = {
import IssuesService._ import IssuesService._
import PullRequestService._ import PullRequestService._
val userName = context.loginAccount.get.userName val userName = loginAccount.userName
val condition = getOrCreateCondition(Keys.Session.DashboardPulls, filter, userName) val condition = getOrCreateCondition(Keys.Session.DashboardPulls, filter, userName)
val allRepos = getAllRepositories(userName) val allRepos = getAllRepositories(userName)
val page = IssueSearchCondition.page(request) val page = IssueSearchCondition.page(request)

View File

@@ -1,6 +1,7 @@
package gitbucket.core.controller package gitbucket.core.controller
import gitbucket.core.issues.html import gitbucket.core.issues.html
import gitbucket.core.model.Account
import gitbucket.core.service.IssuesService._ import gitbucket.core.service.IssuesService._
import gitbucket.core.service._ import gitbucket.core.service._
import gitbucket.core.util.SyntaxSugars._ import gitbucket.core.util.SyntaxSugars._
@@ -95,212 +96,224 @@ trait IssuesControllerBase extends ControllerBase {
}) })
get("/:owner/:repository/issues/:id")(referrersOnly { repository => get("/:owner/:repository/issues/:id")(referrersOnly { repository =>
defining(repository.owner, repository.name, params("id")) { val issueId = params("id")
case (owner, name, issueId) => getIssue(repository.owner, repository.name, issueId) map {
getIssue(owner, name, issueId) map { issue =>
issue => if (issue.isPullRequest) {
if (issue.isPullRequest) { redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}") } else {
} else { html.issue(
html.issue( issue,
issue, getComments(repository.owner, repository.name, issueId.toInt),
getComments(owner, name, issueId.toInt), getIssueLabels(repository.owner, repository.name, issueId.toInt),
getIssueLabels(owner, name, issueId.toInt), getAssignableUserNames(repository.owner, repository.name),
getAssignableUserNames(owner, name), getMilestonesWithIssueCount(repository.owner, repository.name),
getMilestonesWithIssueCount(owner, name), getPriorities(repository.owner, repository.name),
getPriorities(owner, name), getLabels(repository.owner, repository.name),
getLabels(owner, name), isIssueEditable(repository),
isIssueEditable(repository), isIssueManageable(repository),
isIssueManageable(repository), isIssueCommentManageable(repository),
isIssueCommentManageable(repository), repository
repository )
) }
} } getOrElse NotFound()
} getOrElse NotFound()
}
}) })
get("/:owner/:repository/issues/new")(readableUsersOnly { repository => get("/:owner/:repository/issues/new")(readableUsersOnly { repository =>
if (isIssueEditable(repository)) { // TODO Should this check is provided by authenticator? if (isIssueEditable(repository)) { // TODO Should this check is provided by authenticator?
defining(repository.owner, repository.name) { html.create(
case (owner, name) => getAssignableUserNames(repository.owner, repository.name),
html.create( getMilestones(repository.owner, repository.name),
getAssignableUserNames(owner, name), getPriorities(repository.owner, repository.name),
getMilestones(owner, name), getDefaultPriority(repository.owner, repository.name),
getPriorities(owner, name), getLabels(repository.owner, repository.name),
getDefaultPriority(owner, name), isIssueManageable(repository),
getLabels(owner, name), getContentTemplate(repository, "ISSUE_TEMPLATE"),
isIssueManageable(repository), repository
getContentTemplate(repository, "ISSUE_TEMPLATE"), )
repository
)
}
} else Unauthorized() } else Unauthorized()
}) })
post("/:owner/:repository/issues/new", issueCreateForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/issues/new", issueCreateForm)(readableUsersOnly { (form, repository) =>
if (isIssueEditable(repository)) { // TODO Should this check is provided by authenticator? context.withLoginAccount {
val issue = createIssue( loginAccount =>
repository, if (isIssueEditable(repository)) { // TODO Should this check is provided by authenticator?
form.title, val issue = createIssue(
form.content, repository,
form.assignedUserName, form.title,
form.milestoneId, form.content,
form.priorityId, form.assignedUserName,
form.labelNames.toSeq.flatMap(_.split(",")), form.milestoneId,
context.loginAccount.get form.priorityId,
) form.labelNames.toSeq.flatMap(_.split(",")),
loginAccount
redirect(s"/${issue.userName}/${issue.repositoryName}/issues/${issue.issueId}") )
} else Unauthorized() redirect(s"/${issue.userName}/${issue.repositoryName}/issues/${issue.issueId}")
} else Unauthorized()
}
}) })
ajaxPost("/:owner/:repository/issues/edit_title/:id", issueTitleEditForm)(readableUsersOnly { (title, repository) => ajaxPost("/:owner/:repository/issues/edit_title/:id", issueTitleEditForm)(readableUsersOnly { (title, repository) =>
defining(repository.owner, repository.name) { context.withLoginAccount {
case (owner, name) => loginAccount =>
getIssue(owner, name, params("id")).map { getIssue(repository.owner, repository.name, params("id")).map {
issue => issue =>
if (isEditableContent(owner, name, issue.openedUserName)) { if (isEditableContent(repository.owner, repository.name, issue.openedUserName, loginAccount)) {
if (issue.title != title) { if (issue.title != title) {
// update issue // update issue
updateIssue(owner, name, issue.issueId, title, issue.content) updateIssue(repository.owner, repository.name, issue.issueId, title, issue.content)
// extract references and create refer comment // extract references and create refer comment
createReferComment(owner, name, issue.copy(title = title), title, context.loginAccount.get) createReferComment(repository.owner, repository.name, issue.copy(title = title), title, loginAccount)
createComment( createComment(
owner, repository.owner,
name, repository.name,
context.loginAccount.get.userName, loginAccount.userName,
issue.issueId, issue.issueId,
issue.title + "\r\n" + title, issue.title + "\r\n" + title,
"change_title" "change_title"
) )
} }
redirect(s"/${owner}/${name}/issues/_data/${issue.issueId}") redirect(s"/${repository.owner}/${repository.name}/issues/_data/${issue.issueId}")
} else Unauthorized() } else Unauthorized()
} getOrElse NotFound() } getOrElse NotFound()
} }
}) })
ajaxPost("/:owner/:repository/issues/edit/:id", issueEditForm)(readableUsersOnly { (content, repository) => ajaxPost("/:owner/:repository/issues/edit/:id", issueEditForm)(readableUsersOnly { (content, repository) =>
defining(repository.owner, repository.name) { context.withLoginAccount {
case (owner, name) => loginAccount =>
getIssue(owner, name, params("id")).map { issue => getIssue(repository.owner, repository.name, params("id")).map { issue =>
if (isEditableContent(owner, name, issue.openedUserName)) { if (isEditableContent(repository.owner, repository.name, issue.openedUserName, loginAccount)) {
// update issue // update issue
updateIssue(owner, name, issue.issueId, issue.title, content) updateIssue(repository.owner, repository.name, issue.issueId, issue.title, content)
// extract references and create refer comment // extract references and create refer comment
createReferComment(owner, name, issue, content.getOrElse(""), context.loginAccount.get) createReferComment(repository.owner, repository.name, issue, content.getOrElse(""), loginAccount)
redirect(s"/${owner}/${name}/issues/_data/${issue.issueId}") redirect(s"/${repository.owner}/${repository.name}/issues/_data/${issue.issueId}")
} else Unauthorized() } else Unauthorized()
} getOrElse NotFound() } getOrElse NotFound()
} }
}) })
post("/:owner/:repository/issue_comments/new", commentForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/issue_comments/new", commentForm)(readableUsersOnly { (form, repository) =>
getIssue(repository.owner, repository.name, form.issueId.toString).flatMap { issue => context.withLoginAccount {
val actionOpt = loginAccount =>
params.get("action").filter(_ => isEditableContent(issue.userName, issue.repositoryName, issue.openedUserName)) getIssue(repository.owner, repository.name, form.issueId.toString).flatMap { issue =>
handleComment(issue, Some(form.content), repository, actionOpt) map { val actionOpt =
case (issue, id) => params
redirect( .get("action")
s"/${repository.owner}/${repository.name}/${if (issue.isPullRequest) "pull" else "issues"}/${form.issueId}#comment-${id}" .filter(_ => isEditableContent(issue.userName, issue.repositoryName, issue.openedUserName, loginAccount))
) handleComment(issue, Some(form.content), repository, actionOpt) map {
} case (issue, id) =>
} getOrElse NotFound() redirect(
s"/${repository.owner}/${repository.name}/${if (issue.isPullRequest) "pull" else "issues"}/${form.issueId}#comment-${id}"
)
}
} getOrElse NotFound()
}
}) })
post("/:owner/:repository/issue_comments/state", issueStateForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/issue_comments/state", issueStateForm)(readableUsersOnly { (form, repository) =>
getIssue(repository.owner, repository.name, form.issueId.toString).flatMap { issue => context.withLoginAccount {
val actionOpt = loginAccount =>
params.get("action").filter(_ => isEditableContent(issue.userName, issue.repositoryName, issue.openedUserName)) getIssue(repository.owner, repository.name, form.issueId.toString).flatMap { issue =>
handleComment(issue, form.content, repository, actionOpt) map { val actionOpt =
case (issue, id) => params
redirect( .get("action")
s"/${repository.owner}/${repository.name}/${if (issue.isPullRequest) "pull" else "issues"}/${form.issueId}#comment-${id}" .filter(_ => isEditableContent(issue.userName, issue.repositoryName, issue.openedUserName, loginAccount))
) handleComment(issue, form.content, repository, actionOpt) map {
} case (issue, id) =>
} getOrElse NotFound() redirect(
s"/${repository.owner}/${repository.name}/${if (issue.isPullRequest) "pull" else "issues"}/${form.issueId}#comment-${id}"
)
}
} getOrElse NotFound()
}
}) })
ajaxPost("/:owner/:repository/issue_comments/edit/:id", commentForm)(readableUsersOnly { (form, repository) => ajaxPost("/:owner/:repository/issue_comments/edit/:id", commentForm)(readableUsersOnly { (form, repository) =>
defining(repository.owner, repository.name) { context.withLoginAccount {
case (owner, name) => loginAccount =>
getComment(owner, name, params("id")).map { comment => getComment(repository.owner, repository.name, params("id")).map { comment =>
if (isEditableContent(owner, name, comment.commentedUserName)) { if (isEditableContent(repository.owner, repository.name, comment.commentedUserName, loginAccount)) {
updateComment(comment.issueId, comment.commentId, form.content) updateComment(comment.issueId, comment.commentId, form.content)
redirect(s"/${owner}/${name}/issue_comments/_data/${comment.commentId}") redirect(s"/${repository.owner}/${repository.name}/issue_comments/_data/${comment.commentId}")
} else Unauthorized() } else Unauthorized()
} getOrElse NotFound() } getOrElse NotFound()
} }
}) })
ajaxPost("/:owner/:repository/issue_comments/delete/:id")(readableUsersOnly { repository => ajaxPost("/:owner/:repository/issue_comments/delete/:id")(readableUsersOnly { repository =>
defining(repository.owner, repository.name) { context.withLoginAccount { loginAccount =>
case (owner, name) => getComment(repository.owner, repository.name, params("id")).map { comment =>
getComment(owner, name, params("id")).map { comment => if (isDeletableComment(repository.owner, repository.name, comment.commentedUserName, loginAccount)) {
if (isDeletableComment(owner, name, comment.commentedUserName)) { Ok(deleteComment(repository.owner, repository.name, comment.issueId, comment.commentId))
Ok(deleteComment(repository.owner, repository.name, comment.issueId, comment.commentId)) } else Unauthorized()
} else Unauthorized() } getOrElse NotFound()
} getOrElse NotFound()
} }
}) })
ajaxGet("/:owner/:repository/issues/_data/:id")(readableUsersOnly { repository => ajaxGet("/:owner/:repository/issues/_data/:id")(readableUsersOnly { repository =>
getIssue(repository.owner, repository.name, params("id")) map { context.withLoginAccount {
x => loginAccount =>
if (isEditableContent(x.userName, x.repositoryName, x.openedUserName)) { getIssue(repository.owner, repository.name, params("id")) map {
params.get("dataType") collect { x =>
case t if t == "html" => html.editissue(x.content, x.issueId, repository) if (isEditableContent(x.userName, x.repositoryName, x.openedUserName, loginAccount)) {
} getOrElse { params.get("dataType") collect {
contentType = formats("json") case t if t == "html" => html.editissue(x.content, x.issueId, repository)
org.json4s.jackson.Serialization.write( } getOrElse {
Map( contentType = formats("json")
"title" -> x.title, org.json4s.jackson.Serialization.write(
"content" -> Markdown.toHtml( Map(
markdown = x.content getOrElse "No description given.", "title" -> x.title,
repository = repository, "content" -> Markdown.toHtml(
branch = repository.repository.defaultBranch, markdown = x.content getOrElse "No description given.",
enableWikiLink = false, repository = repository,
enableRefsLink = true, branch = repository.repository.defaultBranch,
enableAnchor = true, enableWikiLink = false,
enableLineBreaks = true, enableRefsLink = true,
enableTaskList = true, enableAnchor = true,
hasWritePermission = true enableLineBreaks = true,
enableTaskList = true,
hasWritePermission = true
)
)
) )
) }
) } else Unauthorized()
} } getOrElse NotFound()
} else Unauthorized() }
} getOrElse NotFound()
}) })
ajaxGet("/:owner/:repository/issue_comments/_data/:id")(readableUsersOnly { repository => ajaxGet("/:owner/:repository/issue_comments/_data/:id")(readableUsersOnly { repository =>
getComment(repository.owner, repository.name, params("id")) map { context.withLoginAccount {
x => loginAccount =>
if (isEditableContent(x.userName, x.repositoryName, x.commentedUserName)) { getComment(repository.owner, repository.name, params("id")) map {
params.get("dataType") collect { x =>
case t if t == "html" => html.editcomment(x.content, x.commentId, repository) if (isEditableContent(x.userName, x.repositoryName, x.commentedUserName, loginAccount)) {
} getOrElse { params.get("dataType") collect {
contentType = formats("json") case t if t == "html" => html.editcomment(x.content, x.commentId, repository)
org.json4s.jackson.Serialization.write( } getOrElse {
Map( contentType = formats("json")
"content" -> view.Markdown.toHtml( org.json4s.jackson.Serialization.write(
markdown = x.content, Map(
repository = repository, "content" -> view.Markdown.toHtml(
branch = repository.repository.defaultBranch, markdown = x.content,
enableWikiLink = false, repository = repository,
enableRefsLink = true, branch = repository.repository.defaultBranch,
enableAnchor = true, enableWikiLink = false,
enableLineBreaks = true, enableRefsLink = true,
enableTaskList = true, enableAnchor = true,
hasWritePermission = true enableLineBreaks = true,
enableTaskList = true,
hasWritePermission = true
)
)
) )
) }
) } else Unauthorized()
} } getOrElse NotFound()
} else Unauthorized() }
} getOrElse NotFound()
}) })
ajaxPost("/:owner/:repository/issues/new/label")(writableUsersOnly { repository => ajaxPost("/:owner/:repository/issues/new/label")(writableUsersOnly { repository =>
@@ -353,26 +366,27 @@ trait IssuesControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/issues/batchedit/state")(writableUsersOnly { repository => post("/:owner/:repository/issues/batchedit/state")(writableUsersOnly { repository =>
defining(params.get("value")) { val action = params.get("value")
action => action match {
action match { case Some("open") =>
case Some("open") => executeBatch(repository) { issueId =>
executeBatch(repository) { issueId => getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue => handleComment(issue, None, repository, Some("reopen"))
handleComment(issue, None, repository, Some("reopen")) }
}
}
case Some("close") =>
executeBatch(repository) { issueId =>
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
handleComment(issue, None, repository, Some("close"))
}
}
case _ => BadRequest()
} }
if (params("uri").nonEmpty) { if (params("uri").nonEmpty) {
redirect(params("uri")) redirect(params("uri"))
} }
case Some("close") =>
executeBatch(repository) { issueId =>
getIssue(repository.owner, repository.name, issueId.toString).foreach { issue =>
handleComment(issue, None, repository, Some("close"))
}
}
if (params("uri").nonEmpty) {
redirect(params("uri"))
}
case _ => BadRequest()
} }
}) })
@@ -390,29 +404,26 @@ trait IssuesControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/issues/batchedit/assign")(writableUsersOnly { repository => post("/:owner/:repository/issues/batchedit/assign")(writableUsersOnly { repository =>
defining(assignedUserName("value")) { value => val value = assignedUserName("value")
executeBatch(repository) { executeBatch(repository) {
updateAssignedUserName(repository.owner, repository.name, _, value, true) updateAssignedUserName(repository.owner, repository.name, _, value, true)
} }
if (params("uri").nonEmpty) { if (params("uri").nonEmpty) {
redirect(params("uri")) redirect(params("uri"))
}
} }
}) })
post("/:owner/:repository/issues/batchedit/milestone")(writableUsersOnly { repository => post("/:owner/:repository/issues/batchedit/milestone")(writableUsersOnly { repository =>
defining(milestoneId("value")) { value => val value = milestoneId("value")
executeBatch(repository) { executeBatch(repository) {
updateMilestoneId(repository.owner, repository.name, _, value, true) updateMilestoneId(repository.owner, repository.name, _, value, true)
}
} }
}) })
post("/:owner/:repository/issues/batchedit/priority")(writableUsersOnly { repository => post("/:owner/:repository/issues/batchedit/priority")(writableUsersOnly { repository =>
defining(priorityId("value")) { value => val value = priorityId("value")
executeBatch(repository) { executeBatch(repository) {
updatePriorityId(repository.owner, repository.name, _, value, true) updatePriorityId(repository.owner, repository.name, _, value, true)
}
} }
}) })
@@ -464,48 +475,51 @@ trait IssuesControllerBase extends ControllerBase {
} }
private def searchIssues(repository: RepositoryService.RepositoryInfo) = { private def searchIssues(repository: RepositoryService.RepositoryInfo) = {
defining(repository.owner, repository.name) { val page = IssueSearchCondition.page(request)
case (owner, repoName) => // retrieve search condition
val page = IssueSearchCondition.page(request) val condition = IssueSearchCondition(request)
// retrieve search condition // search issues
val condition = IssueSearchCondition(request) val issues =
// search issues searchIssue(
val issues = condition,
searchIssue(condition, IssueSearchOption.Issues, (page - 1) * IssueLimit, IssueLimit, owner -> repoName) IssueSearchOption.Issues,
(page - 1) * IssueLimit,
IssueLimit,
repository.owner -> repository.name
)
html.list( html.list(
"issues", "issues",
issues.map(issue => (issue, None)), issues.map(issue => (issue, None)),
page, page,
getAssignableUserNames(owner, repoName), getAssignableUserNames(repository.owner, repository.name),
getMilestones(owner, repoName), getMilestones(repository.owner, repository.name),
getPriorities(owner, repoName), getPriorities(repository.owner, repository.name),
getLabels(owner, repoName), getLabels(repository.owner, repository.name),
countIssue(condition.copy(state = "open"), IssueSearchOption.Issues, owner -> repoName), countIssue(condition.copy(state = "open"), IssueSearchOption.Issues, repository.owner -> repository.name),
countIssue(condition.copy(state = "closed"), IssueSearchOption.Issues, owner -> repoName), countIssue(condition.copy(state = "closed"), IssueSearchOption.Issues, repository.owner -> repository.name),
condition, condition,
repository, repository,
isIssueEditable(repository), isIssueEditable(repository),
isIssueManageable(repository) isIssueManageable(repository)
) )
}
} }
/** /**
* Tests whether an issue or a comment is editable by a logged-in user. * Tests whether an issue or a comment is editable by a logged-in user.
*/ */
private def isEditableContent(owner: String, repository: String, author: String)( private def isEditableContent(owner: String, repository: String, author: String, loginAccount: Account)(
implicit context: Context implicit context: Context
): Boolean = { ): Boolean = {
hasDeveloperRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName hasDeveloperRole(owner, repository, context.loginAccount) || author == loginAccount.userName
} }
/** /**
* Tests whether an issue comment is deletable by a logged-in user. * Tests whether an issue comment is deletable by a logged-in user.
*/ */
private def isDeletableComment(owner: String, repository: String, author: String)( private def isDeletableComment(owner: String, repository: String, author: String, loginAccount: Account)(
implicit context: Context implicit context: Context
): Boolean = { ): Boolean = {
hasOwnerRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName hasOwnerRole(owner, repository, context.loginAccount) || author == loginAccount.userName
} }
} }

View File

@@ -8,7 +8,6 @@ import gitbucket.core.service.IssuesService._
import gitbucket.core.service.PullRequestService._ import gitbucket.core.service.PullRequestService._
import gitbucket.core.service.RepositoryService.RepositoryInfo import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service._ import gitbucket.core.service._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util._ import gitbucket.core.util._
@@ -111,24 +110,29 @@ trait PullRequestsControllerBase extends ControllerBase {
get("/:owner/:repository/pull/:id")(referrersOnly { repository => get("/:owner/:repository/pull/:id")(referrersOnly { repository =>
params("id").toIntOpt.flatMap { params("id").toIntOpt.flatMap {
issueId => issueId =>
val owner = repository.owner getPullRequest(repository.owner, repository.name, issueId) map {
val name = repository.name
getPullRequest(owner, name, issueId) map {
case (issue, pullreq) => case (issue, pullreq) =>
val (commits, diffs) = val (commits, diffs) =
getRequestCompareInfo(owner, name, pullreq.commitIdFrom, owner, name, pullreq.commitIdTo) getRequestCompareInfo(
repository.owner,
repository.name,
pullreq.commitIdFrom,
repository.owner,
repository.name,
pullreq.commitIdTo
)
html.conversation( html.conversation(
issue, issue,
pullreq, pullreq,
commits.flatten, commits.flatten,
getPullRequestComments(owner, name, issue.issueId, commits.flatten), getPullRequestComments(repository.owner, repository.name, issue.issueId, commits.flatten),
diffs.size, diffs.size,
getIssueLabels(owner, name, issueId), getIssueLabels(repository.owner, repository.name, issueId),
getAssignableUserNames(owner, name), getAssignableUserNames(repository.owner, repository.name),
getMilestonesWithIssueCount(owner, name), getMilestonesWithIssueCount(repository.owner, repository.name),
getPriorities(owner, name), getPriorities(repository.owner, repository.name),
getLabels(owner, name), getLabels(repository.owner, repository.name),
isEditable(repository), isEditable(repository),
isManageable(repository), isManageable(repository),
hasDeveloperRole(pullreq.requestUserName, pullreq.requestRepositoryName, context.loginAccount), hasDeveloperRole(pullreq.requestUserName, pullreq.requestRepositoryName, context.loginAccount),
@@ -162,12 +166,17 @@ trait PullRequestsControllerBase extends ControllerBase {
get("/:owner/:repository/pull/:id/commits")(referrersOnly { repository => get("/:owner/:repository/pull/:id/commits")(referrersOnly { repository =>
params("id").toIntOpt.flatMap { params("id").toIntOpt.flatMap {
issueId => issueId =>
val owner = repository.owner getPullRequest(repository.owner, repository.name, issueId) map {
val name = repository.name
getPullRequest(owner, name, issueId) map {
case (issue, pullreq) => case (issue, pullreq) =>
val (commits, diffs) = val (commits, diffs) =
getRequestCompareInfo(owner, name, pullreq.commitIdFrom, owner, name, pullreq.commitIdTo) getRequestCompareInfo(
repository.owner,
repository.name,
pullreq.commitIdFrom,
repository.owner,
repository.name,
pullreq.commitIdTo
)
val commitsWithStatus = commits.map { day => val commitsWithStatus = commits.map { day =>
day.map { commit => day.map { commit =>
@@ -179,7 +188,7 @@ trait PullRequestsControllerBase extends ControllerBase {
issue, issue,
pullreq, pullreq,
commitsWithStatus, commitsWithStatus,
getPullRequestComments(owner, name, issue.issueId, commits.flatten), getPullRequestComments(repository.owner, repository.name, issue.issueId, commits.flatten),
diffs.size, diffs.size,
isManageable(repository), isManageable(repository),
repository repository
@@ -191,19 +200,24 @@ trait PullRequestsControllerBase extends ControllerBase {
get("/:owner/:repository/pull/:id/files")(referrersOnly { repository => get("/:owner/:repository/pull/:id/files")(referrersOnly { repository =>
params("id").toIntOpt.flatMap { params("id").toIntOpt.flatMap {
issueId => issueId =>
val owner = repository.owner getPullRequest(repository.owner, repository.name, issueId) map {
val name = repository.name
getPullRequest(owner, name, issueId) map {
case (issue, pullreq) => case (issue, pullreq) =>
val (commits, diffs) = val (commits, diffs) =
getRequestCompareInfo(owner, name, pullreq.commitIdFrom, owner, name, pullreq.commitIdTo) getRequestCompareInfo(
repository.owner,
repository.name,
pullreq.commitIdFrom,
repository.owner,
repository.name,
pullreq.commitIdTo
)
html.files( html.files(
issue, issue,
pullreq, pullreq,
diffs, diffs,
commits.flatten, commits.flatten,
getPullRequestComments(owner, name, issue.issueId, commits.flatten), getPullRequestComments(repository.owner, repository.name, issue.issueId, commits.flatten),
isManageable(repository), isManageable(repository),
repository repository
) )
@@ -214,20 +228,20 @@ trait PullRequestsControllerBase extends ControllerBase {
ajaxGet("/:owner/:repository/pull/:id/mergeguide")(referrersOnly { repository => ajaxGet("/:owner/:repository/pull/:id/mergeguide")(referrersOnly { repository =>
params("id").toIntOpt.flatMap { params("id").toIntOpt.flatMap {
issueId => issueId =>
val owner = repository.owner getPullRequest(repository.owner, repository.name, issueId) map {
val name = repository.name
getPullRequest(owner, name, issueId) map {
case (issue, pullreq) => case (issue, pullreq) =>
val conflictMessage = LockUtil.lock(s"${owner}/${name}") { val conflictMessage = LockUtil.lock(s"${repository.owner}/${repository.name}") {
checkConflict(owner, name, pullreq.branch, issueId) checkConflict(repository.owner, repository.name, pullreq.branch, issueId)
} }
val hasMergePermission = hasDeveloperRole(owner, name, context.loginAccount) val hasMergePermission = hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.branch) val branchProtection = getProtectedBranchInfo(repository.owner, repository.name, pullreq.branch)
val mergeStatus = PullRequestService.MergeStatus( val mergeStatus = PullRequestService.MergeStatus(
conflictMessage = conflictMessage, conflictMessage = conflictMessage,
commitStatuses = getCommitStatuses(owner, name, pullreq.commitIdTo), commitStatuses = getCommitStatuses(repository.owner, repository.name, pullreq.commitIdTo),
branchProtection = branchProtection, branchProtection = branchProtection,
branchIsOutOfDate = JGitUtil.getShaByRef(owner, name, pullreq.branch) != Some(pullreq.commitIdFrom), branchIsOutOfDate = JGitUtil.getShaByRef(repository.owner, repository.name, pullreq.branch) != Some(
pullreq.commitIdFrom
),
needStatusCheck = context.loginAccount needStatusCheck = context.loginAccount
.map { u => .map { u =>
branchProtection.needStatusCheck(u.userName) branchProtection.needStatusCheck(u.userName)
@@ -363,23 +377,22 @@ trait PullRequestsControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/pull/:id/merge", mergeForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/pull/:id/merge", mergeForm)(writableUsersOnly { (form, repository) =>
params("id").toIntOpt.flatMap { issueId => context.withLoginAccount { loginAccount =>
val owner = repository.owner params("id").toIntOpt.flatMap { issueId =>
val name = repository.name mergePullRequest(
repository,
mergePullRequest( issueId,
repository, loginAccount,
issueId, form.message,
context.loginAccount.get, form.strategy,
form.message, form.isDraft,
form.strategy, context.settings
form.isDraft, ) match {
context.settings case Right(objectId) => redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
) match { case Left(message) => Some(BadRequest(message))
case Right(objectId) => redirect(s"/${owner}/${name}/pull/${issueId}") }
case Left(message) => Some(BadRequest(message)) } getOrElse NotFound()
} }
} getOrElse NotFound()
}) })
get("/:owner/:repository/compare")(referrersOnly { forkedRepository => get("/:owner/:repository/compare")(referrersOnly { forkedRepository =>
@@ -549,15 +562,14 @@ trait PullRequestsControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/pulls/new", pullRequestForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/pulls/new", pullRequestForm)(readableUsersOnly { (form, repository) =>
defining(repository.owner, repository.name) { context.withLoginAccount {
case (owner, name) => loginAccount =>
val manageable = isManageable(repository) val manageable = isManageable(repository)
val loginUserName = context.loginAccount.get.userName
val issueId = insertIssue( val issueId = insertIssue(
owner = repository.owner, owner = repository.owner,
repository = repository.name, repository = repository.name,
loginUser = loginUserName, loginUser = loginAccount.userName,
title = form.title, title = form.title,
content = form.content, content = form.content,
assignedUserName = if (manageable) form.assignedUserName else None, assignedUserName = if (manageable) form.assignedUserName else None,
@@ -576,14 +588,14 @@ trait PullRequestsControllerBase extends ControllerBase {
commitIdFrom = form.commitIdFrom, commitIdFrom = form.commitIdFrom,
commitIdTo = form.commitIdTo, commitIdTo = form.commitIdTo,
isDraft = form.isDraft, isDraft = form.isDraft,
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) )
// insert labels // insert labels
if (manageable) { if (manageable) {
form.labelNames.foreach { value => form.labelNames.foreach { value =>
val labels = getLabels(owner, name) val labels = getLabels(repository.owner, repository.name)
value.split(",").foreach { labelName => value.split(",").foreach { labelName =>
labels.find(_.labelName == labelName).map { label => labels.find(_.labelName == labelName).map { label =>
registerIssueLabel(repository.owner, repository.name, issueId, label.labelId) registerIssueLabel(repository.owner, repository.name, issueId, label.labelId)
@@ -592,7 +604,7 @@ trait PullRequestsControllerBase extends ControllerBase {
} }
} }
redirect(s"/${owner}/${name}/pull/${issueId}") redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} }
}) })
@@ -639,44 +651,42 @@ trait PullRequestsControllerBase extends ControllerBase {
html.proposals(proposedBranches, targetRepository, repository) html.proposals(proposedBranches, targetRepository, repository)
}) })
private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) = private def searchPullRequests(userName: Option[String], repository: RepositoryService.RepositoryInfo) = {
defining(repository.owner, repository.name) { val page = IssueSearchCondition.page(request)
case (owner, repoName) => // retrieve search condition
val page = IssueSearchCondition.page(request) val condition = IssueSearchCondition(request)
// retrieve search condition // search issues
val condition = IssueSearchCondition(request) val issues = searchIssue(
// search issues condition,
val issues = searchIssue( IssueSearchOption.PullRequests,
condition, (page - 1) * PullRequestLimit,
IssueSearchOption.PullRequests, PullRequestLimit,
(page - 1) * PullRequestLimit, repository.owner -> repository.name
PullRequestLimit, )
owner -> repoName // commit status
) val status = issues.map { issue =>
// commit status issue.commitId.flatMap { commitId =>
val status = issues.map { issue => getCommitStatusWithSummary(repository.owner, repository.name, commitId)
issue.commitId.flatMap { commitId => }
getCommitStatusWithSummary(owner, repoName, commitId)
}
}
gitbucket.core.issues.html.list(
"pulls",
issues.zip(status),
page,
getAssignableUserNames(owner, repoName),
getMilestones(owner, repoName),
getPriorities(owner, repoName),
getLabels(owner, repoName),
countIssue(condition.copy(state = "open"), IssueSearchOption.PullRequests, owner -> repoName),
countIssue(condition.copy(state = "closed"), IssueSearchOption.PullRequests, owner -> repoName),
condition,
repository,
isEditable(repository),
isManageable(repository)
)
} }
gitbucket.core.issues.html.list(
"pulls",
issues.zip(status),
page,
getAssignableUserNames(repository.owner, repository.name),
getMilestones(repository.owner, repository.name),
getPriorities(repository.owner, repository.name),
getLabels(repository.owner, repository.name),
countIssue(condition.copy(state = "open"), IssueSearchOption.PullRequests, repository.owner -> repository.name),
countIssue(condition.copy(state = "closed"), IssueSearchOption.PullRequests, repository.owner -> repository.name),
condition,
repository,
isEditable(repository),
isManageable(repository)
)
}
/** /**
* Tests whether an logged-in user can manage pull requests. * Tests whether an logged-in user can manage pull requests.
*/ */

View File

@@ -106,32 +106,33 @@ trait ReleaseControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/releases/:tag/create", releaseForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/releases/:tag/create", releaseForm)(writableUsersOnly { (form, repository) =>
val tagName = params("tag") context.withLoginAccount {
val loginAccount = context.loginAccount.get loginAccount =>
val tagName = params("tag")
// Insert into RELEASE
createRelease(repository.owner, repository.name, form.name, form.content, tagName, loginAccount)
// Insert into RELEASE // Insert into RELEASE_ASSET
createRelease(repository.owner, repository.name, form.name, form.content, tagName, loginAccount) val files = params.toMap.collect {
case (name, value) if name.startsWith("file:") =>
val Array(_, fileId) = name.split(":")
(fileId, value)
}
files.foreach {
case (fileId, fileName) =>
val size =
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
// Insert into RELEASE_ASSET val releaseInfo = ReleaseInfo(repository.owner, repository.name, loginAccount.userName, form.name, tagName)
val files = params.toMap.collect { recordActivity(releaseInfo)
case (name, value) if name.startsWith("file:") =>
val Array(_, fileId) = name.split(":") redirect(s"/${repository.owner}/${repository.name}/releases/${tagName}")
(fileId, value)
} }
files.foreach {
case (fileId, fileName) =>
val size =
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
val releaseInfo = ReleaseInfo(repository.owner, repository.name, loginAccount.userName, form.name, tagName)
recordActivity(releaseInfo)
redirect(s"/${repository.owner}/${repository.name}/releases/${tagName}")
}) })
get("/:owner/:repository/changelog/*...*")(writableUsersOnly { repository => get("/:owner/:repository/changelog/*...*")(writableUsersOnly { repository =>
@@ -168,48 +169,50 @@ trait ReleaseControllerBase extends ControllerBase {
}).getOrElse(NotFound()) }).getOrElse(NotFound())
}) })
post("/:owner/:repository/releases/:tag/edit", releaseForm)(writableUsersOnly { post("/:owner/:repository/releases/:tag/edit", releaseForm)(writableUsersOnly { (form, repository) =>
(form, repository) => context.withLoginAccount {
val tagName = params("tag") loginAccount =>
val loginAccount = context.loginAccount.get val tagName = params("tag")
getRelease(repository.owner, repository.name, tagName) getRelease(repository.owner, repository.name, tagName)
.map { release => .map {
// Update RELEASE release =>
updateRelease(repository.owner, repository.name, tagName, form.name, form.content) // Update RELEASE
updateRelease(repository.owner, repository.name, tagName, form.name, form.content)
// Delete and Insert RELEASE_ASSET // Delete and Insert RELEASE_ASSET
val assets = getReleaseAssets(repository.owner, repository.name, tagName) val assets = getReleaseAssets(repository.owner, repository.name, tagName)
deleteReleaseAssets(repository.owner, repository.name, tagName) deleteReleaseAssets(repository.owner, repository.name, tagName)
val files = params.toMap.collect { val files = params.toMap.collect {
case (name, value) if name.startsWith("file:") => case (name, value) if name.startsWith("file:") =>
val Array(_, fileId) = name.split(":") val Array(_, fileId) = name.split(":")
(fileId, value) (fileId, value)
}
files.foreach {
case (fileId, fileName) =>
val size =
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
assets.foreach { asset =>
if (!files.exists { case (fileId, _) => fileId == asset.fileName }) {
val file = new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(release.tag + "/" + asset.fileName)
)
FileUtils.forceDelete(file)
}
}
redirect(s"/${release.userName}/${release.repositoryName}/releases/${tagName}")
} }
files.foreach { .getOrElse(NotFound())
case (fileId, fileName) => }
val size =
new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(tagName + "/" + fileId)
).length
createReleaseAsset(repository.owner, repository.name, tagName, fileId, fileName, size, loginAccount)
}
assets.foreach { asset =>
if (!files.exists { case (fileId, _) => fileId == asset.fileName }) {
val file = new File(
getReleaseFilesDir(repository.owner, repository.name),
FileUtil.checkFilename(release.tag + "/" + asset.fileName)
)
FileUtils.forceDelete(file)
}
}
redirect(s"/${release.userName}/${release.repositoryName}/releases/${tagName}")
}
.getOrElse(NotFound())
}) })
post("/:owner/:repository/releases/:tag/delete")(writableUsersOnly { repository => post("/:owner/:repository/releases/:tag/delete")(writableUsersOnly { repository =>

View File

@@ -385,54 +385,62 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* Rename repository. * Rename repository.
*/ */
post("/:owner/:repository/settings/rename", renameForm)(ownerOnly { (form, repository) => post("/:owner/:repository/settings/rename", renameForm)(ownerOnly { (form, repository) =>
if (context.settings.repositoryOperation.rename || context.loginAccount.get.isAdmin) { context.withLoginAccount {
if (repository.name != form.repositoryName) { loginAccount =>
// Update database and move git repository if (context.settings.repositoryOperation.rename || loginAccount.isAdmin) {
renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName) if (repository.name != form.repositoryName) {
// Record activity log // Update database and move git repository
val renameInfo = RenameRepositoryInfo( renameRepository(repository.owner, repository.name, repository.owner, form.repositoryName)
repository.owner, // Record activity log
form.repositoryName, val renameInfo = RenameRepositoryInfo(
context.loginAccount.get.userName, repository.owner,
repository.name form.repositoryName,
) loginAccount.userName,
recordActivity(renameInfo) repository.name
} )
redirect(s"/${repository.owner}/${form.repositoryName}") recordActivity(renameInfo)
} else Forbidden() }
redirect(s"/${repository.owner}/${form.repositoryName}")
} else Forbidden()
}
}) })
/** /**
* Transfer repository ownership. * Transfer repository ownership.
*/ */
post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) => post("/:owner/:repository/settings/transfer", transferForm)(ownerOnly { (form, repository) =>
if (context.settings.repositoryOperation.transfer || context.loginAccount.get.isAdmin) { context.withLoginAccount {
// Change repository owner loginAccount =>
if (repository.owner != form.newOwner) { if (context.settings.repositoryOperation.transfer || loginAccount.isAdmin) {
// Update database and move git repository // Change repository owner
renameRepository(repository.owner, repository.name, form.newOwner, repository.name) if (repository.owner != form.newOwner) {
// Record activity log // Update database and move git repository
val renameInfo = RenameRepositoryInfo( renameRepository(repository.owner, repository.name, form.newOwner, repository.name)
form.newOwner, // Record activity log
repository.name, val renameInfo = RenameRepositoryInfo(
context.loginAccount.get.userName, form.newOwner,
repository.owner repository.name,
) loginAccount.userName,
recordActivity(renameInfo) repository.owner
} )
redirect(s"/${form.newOwner}/${repository.name}") recordActivity(renameInfo)
} else Forbidden() }
redirect(s"/${form.newOwner}/${repository.name}")
} else Forbidden()
}
}) })
/** /**
* Delete the repository. * Delete the repository.
*/ */
post("/:owner/:repository/settings/delete")(ownerOnly { repository => post("/:owner/:repository/settings/delete")(ownerOnly { repository =>
if (context.settings.repositoryOperation.delete || context.loginAccount.get.isAdmin) { context.withLoginAccount { loginAccount =>
// Delete the repository and related files if (context.settings.repositoryOperation.delete || loginAccount.isAdmin) {
deleteRepository(repository.repository) // Delete the repository and related files
redirect(s"/${repository.owner}") deleteRepository(repository.repository)
} else Forbidden() redirect(s"/${repository.owner}")
} else Forbidden()
}
}) })
/** /**

View File

@@ -10,7 +10,6 @@ import gitbucket.core.service._
import gitbucket.core.service.RepositoryCommitFileService.CommitFile import gitbucket.core.service.RepositoryCommitFileService.CommitFile
import gitbucket.core.util._ import gitbucket.core.util._
import gitbucket.core.util.StringUtil._ import gitbucket.core.util.StringUtil._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.Directory._ import gitbucket.core.util.Directory._
import gitbucket.core.model.{Account, WebHook} import gitbucket.core.model.{Account, WebHook}
@@ -221,11 +220,8 @@ trait RepositoryViewerControllerBase extends ControllerBase {
gitbucket.core.repo.html.creating(owner, repository) gitbucket.core.repo.html.creating(owner, repository)
} else { } else {
params.get("go-get") match { params.get("go-get") match {
case Some("1") => case Some("1") => getRepository(owner, repository).map(gitbucket.core.html.goget(_)) getOrElse NotFound()
defining(request.paths) { paths => case _ => referrersOnly(fileList(_))
getRepository(owner, repository).map(gitbucket.core.html.goget(_)) getOrElse NotFound()
}
case _ => referrersOnly(fileList(_))
} }
} }
} }
@@ -306,74 +302,99 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}) })
get("/:owner/:repository/new/*")(writableUsersOnly { repository => get("/:owner/:repository/new/*")(writableUsersOnly { repository =>
val (branch, path) = repository.splitPath(multiParams("splat").head) context.withLoginAccount {
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch) loginAccount =>
.needStatusCheck(context.loginAccount.get.userName) val (branch, path) = repository.splitPath(multiParams("splat").head)
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch)
.needStatusCheck(loginAccount.userName)
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch))
html.editor( html.editor(
branch = branch, branch = branch,
repository = repository, repository = repository,
pathList = if (path.length == 0) Nil else path.split("/").toList, pathList = if (path.length == 0) Nil else path.split("/").toList,
fileName = None, fileName = None,
content = JGitUtil.ContentInfo("text", None, None, Some("UTF-8")), content = JGitUtil.ContentInfo("text", None, None, Some("UTF-8")),
protectedBranch = protectedBranch, protectedBranch = protectedBranch,
commit = revCommit.getName commit = revCommit.getName
) )
}
} }
}) })
get("/:owner/:repository/upload/*")(writableUsersOnly { repository => get("/:owner/:repository/upload/*")(writableUsersOnly { repository =>
val (branch, path) = repository.splitPath(multiParams("splat").head) context.withLoginAccount {
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch) loginAccount =>
.needStatusCheck(context.loginAccount.get.userName) val (branch, path) = repository.splitPath(multiParams("splat").head)
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch)
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) .needStatusCheck(loginAccount.userName)
html.upload( Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
branch, val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch))
repository, html.upload(
if (path.length == 0) Nil else path.split("/").toList, branch,
protectedBranch, repository,
revCommit.name if (path.length == 0) Nil else path.split("/").toList,
) protectedBranch,
revCommit.name
)
}
} }
}) })
post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/upload", uploadForm)(writableUsersOnly { (form, repository) =>
val files = form.uploadFiles.split("\n").map { line => context.withLoginAccount {
val i = line.indexOf(':') loginAccount =>
CommitFile(line.substring(0, i).trim, line.substring(i + 1).trim) val files = form.uploadFiles
.split("\n")
.map { line =>
val i = line.indexOf(':')
CommitFile(line.substring(0, i).trim, line.substring(i + 1).trim)
}
.toSeq
val newFiles = files.map { file =>
file.copy(name = if (form.path.length == 0) file.name else s"${form.path}/${file.name}")
}.toSeq
if (form.newBranch) {
val newBranchName = createNewBranchForPullRequest(repository, form.branch, loginAccount)
val objectId = _commit(newBranchName, files, newFiles, loginAccount)
val issueId =
createIssueAndPullRequest(
repository,
form.branch,
newBranchName,
form.commit,
objectId.name,
form.message,
loginAccount
)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} else {
_commit(form.branch, files, newFiles, loginAccount)
if (form.path.length == 0) {
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}")
} else {
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}/${form.path}")
}
}
} }
val newFiles = files.map { file => def _commit(
file.copy(name = if (form.path.length == 0) file.name else s"${form.path}/${file.name}") branchName: String,
} files: Seq[CommitFile],
newFiles: Seq[CommitFile],
if (form.newBranch) { loginAccount: Account
val newBranchName = createNewBranchForPullRequest(repository, form.branch) ): ObjectId = {
val objectId = _commit(newBranchName)
val issueId =
createIssueAndPullRequest(repository, form.branch, newBranchName, form.commit, objectId.name, form.message)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} else {
_commit(form.branch)
if (form.path.length == 0) {
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}")
} else {
redirect(s"/${repository.owner}/${repository.name}/tree/${form.branch}/${form.path}")
}
}
def _commit(branchName: String): ObjectId = {
commitFiles( commitFiles(
repository = repository, repository = repository,
branch = branchName, branch = branchName,
path = form.path, path = form.path,
files = files.toIndexedSeq, files = files.toIndexedSeq,
message = form.message.getOrElse("Add files via upload"), message = form.message.getOrElse("Add files via upload"),
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) { ) {
case (git, headTip, builder, inserter) => case (git, headTip, builder, inserter) =>
@@ -396,32 +417,36 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}) })
get("/:owner/:repository/edit/*")(writableUsersOnly { repository => get("/:owner/:repository/edit/*")(writableUsersOnly { repository =>
val (branch, path) = repository.splitPath(multiParams("splat").head) context.withLoginAccount {
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch) loginAccount =>
.needStatusCheck(context.loginAccount.get.userName) val (branch, path) = repository.splitPath(multiParams("splat").head)
val protectedBranch = getProtectedBranchInfo(repository.owner, repository.name, branch)
.needStatusCheck(loginAccount.userName)
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) {
git => git =>
val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch)) val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(branch))
getPathObjectId(git, path, revCommit).map { getPathObjectId(git, path, revCommit)
objectId => .map {
val paths = path.split("/") objectId =>
val info = EditorConfigUtil.getEditorConfigInfo(git, branch, path) val paths = path.split("/")
val info = EditorConfigUtil.getEditorConfigInfo(git, branch, path)
html.editor( html.editor(
branch = branch, branch = branch,
repository = repository, repository = repository,
pathList = paths.take(paths.size - 1).toList, pathList = paths.take(paths.size - 1).toList,
fileName = Some(paths.last), fileName = Some(paths.last),
content = JGitUtil.getContentInfo(git, path, objectId), content = JGitUtil.getContentInfo(git, path, objectId),
protectedBranch = protectedBranch, protectedBranch = protectedBranch,
commit = revCommit.getName, commit = revCommit.getName,
newLineMode = info.newLineMode, newLineMode = info.newLineMode,
useSoftTabs = info.useSoftTabs, useSoftTabs = info.useSoftTabs,
tabSize = info.tabSize tabSize = info.tabSize
) )
} getOrElse NotFound() } getOrElse NotFound()
}
} }
}) })
@@ -446,21 +471,32 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/create", editorForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/create", editorForm)(writableUsersOnly { (form, repository) =>
if (form.newBranch) { context.withLoginAccount {
val newBranchName = createNewBranchForPullRequest(repository, form.branch) loginAccount =>
val objectId = _commit(newBranchName) if (form.newBranch) {
val issueId = val newBranchName = createNewBranchForPullRequest(repository, form.branch, loginAccount)
createIssueAndPullRequest(repository, form.branch, newBranchName, form.commit, objectId.name, form.message) val objectId = _commit(newBranchName, loginAccount)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}") val issueId =
} else { createIssueAndPullRequest(
_commit(form.branch) repository,
redirect( form.branch,
s"/${repository.owner}/${repository.name}/blob/${form.branch}/${if (form.path.length == 0) urlEncode(form.newFileName) newBranchName,
else s"${form.path}/${urlEncode(form.newFileName)}"}" form.commit,
) objectId.name,
form.message,
loginAccount
)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} else {
_commit(form.branch, loginAccount)
redirect(
s"/${repository.owner}/${repository.name}/blob/${form.branch}/${if (form.path.length == 0) urlEncode(form.newFileName)
else s"${form.path}/${urlEncode(form.newFileName)}"}"
)
}
} }
def _commit(branchName: String): ObjectId = { def _commit(branchName: String, loginAccount: Account): ObjectId = {
commitFile( commitFile(
repository = repository, repository = repository,
branch = branchName, branch = branchName,
@@ -471,28 +507,39 @@ trait RepositoryViewerControllerBase extends ControllerBase {
charset = form.charset, charset = form.charset,
message = form.message.getOrElse(s"Create ${form.newFileName}"), message = form.message.getOrElse(s"Create ${form.newFileName}"),
commit = form.commit, commit = form.commit,
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) )
} }
}) })
post("/:owner/:repository/update", editorForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/update", editorForm)(writableUsersOnly { (form, repository) =>
if (form.newBranch) { context.withLoginAccount {
val newBranchName = createNewBranchForPullRequest(repository, form.branch) loginAccount =>
val objectId = _commit(newBranchName) if (form.newBranch) {
val issueId = val newBranchName = createNewBranchForPullRequest(repository, form.branch, loginAccount)
createIssueAndPullRequest(repository, form.branch, newBranchName, form.commit, objectId.name, form.message) val objectId = _commit(newBranchName, loginAccount)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}") val issueId =
} else { createIssueAndPullRequest(
_commit(form.branch) repository,
redirect( form.branch,
s"/${repository.owner}/${repository.name}/blob/${urlEncode(form.branch)}/${if (form.path.length == 0) urlEncode(form.newFileName) newBranchName,
else s"${form.path}/${urlEncode(form.newFileName)}"}" form.commit,
) objectId.name,
form.message,
loginAccount
)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} else {
_commit(form.branch, loginAccount)
redirect(
s"/${repository.owner}/${repository.name}/blob/${urlEncode(form.branch)}/${if (form.path.length == 0) urlEncode(form.newFileName)
else s"${form.path}/${urlEncode(form.newFileName)}"}"
)
}
} }
def _commit(branchName: String): ObjectId = { def _commit(branchName: String, loginAccount: Account): ObjectId = {
commitFile( commitFile(
repository = repository, repository = repository,
branch = branchName, branch = branchName,
@@ -507,28 +554,39 @@ trait RepositoryViewerControllerBase extends ControllerBase {
form.message.getOrElse(s"Rename ${form.oldFileName.get} to ${form.newFileName}") form.message.getOrElse(s"Rename ${form.oldFileName.get} to ${form.newFileName}")
}, },
commit = form.commit, commit = form.commit,
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) )
} }
}) })
post("/:owner/:repository/remove", deleteForm)(writableUsersOnly { (form, repository) => post("/:owner/:repository/remove", deleteForm)(writableUsersOnly { (form, repository) =>
if (form.newBranch) { context.withLoginAccount {
val newBranchName = createNewBranchForPullRequest(repository, form.branch) loginAccount =>
val objectId = _commit(newBranchName) if (form.newBranch) {
val issueId = val newBranchName = createNewBranchForPullRequest(repository, form.branch, loginAccount)
createIssueAndPullRequest(repository, form.branch, newBranchName, form.commit, objectId.name, form.message) val objectId = _commit(newBranchName, loginAccount)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}") val issueId =
} else { createIssueAndPullRequest(
_commit(form.branch) repository,
redirect( form.branch,
s"/${repository.owner}/${repository.name}/tree/${form.branch}${if (form.path.length == 0) "" newBranchName,
else "/" + form.path}" form.commit,
) objectId.name,
form.message,
loginAccount
)
redirect(s"/${repository.owner}/${repository.name}/pull/${issueId}")
} else {
_commit(form.branch, loginAccount)
redirect(
s"/${repository.owner}/${repository.name}/tree/${form.branch}${if (form.path.length == 0) ""
else "/" + form.path}"
)
}
} }
def _commit(branchName: String): ObjectId = { def _commit(branchName: String, loginAccount: Account): ObjectId = {
commitFile( commitFile(
repository = repository, repository = repository,
branch = branchName, branch = branchName,
@@ -539,23 +597,27 @@ trait RepositoryViewerControllerBase extends ControllerBase {
charset = "", charset = "",
message = form.message.getOrElse(s"Delete ${form.fileName}"), message = form.message.getOrElse(s"Delete ${form.fileName}"),
commit = form.commit, commit = form.commit,
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) )
} }
}) })
private def getNewBranchName(repository: RepositoryInfo): String = { private def getNewBranchName(repository: RepositoryInfo, loginAccount: Account): String = {
var i = 1 var i = 1
val branchNamePrefix = cutTail(context.loginAccount.get.userName.replaceAll("[^a-zA-Z0-9-_]", "-"), 25) val branchNamePrefix = cutTail(loginAccount.userName.replaceAll("[^a-zA-Z0-9-_]", "-"), 25)
while (repository.branchList.exists(p => p.contains(s"$branchNamePrefix-patch-$i"))) { while (repository.branchList.exists(p => p.contains(s"$branchNamePrefix-patch-$i"))) {
i += 1 i += 1
} }
s"$branchNamePrefix-patch-$i" s"$branchNamePrefix-patch-$i"
} }
private def createNewBranchForPullRequest(repository: RepositoryInfo, baseBranchName: String): String = { private def createNewBranchForPullRequest(
val newBranchName = getNewBranchName(repository) repository: RepositoryInfo,
baseBranchName: String,
loginAccount: Account
): String = {
val newBranchName = getNewBranchName(repository, loginAccount)
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
JGitUtil.createBranch(git, baseBranchName, newBranchName) JGitUtil.createBranch(git, baseBranchName, newBranchName)
} }
@@ -563,7 +625,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
val settings = loadSystemSettings() val settings = loadSystemSettings()
callWebHookOf(repository.owner, repository.name, WebHook.Create, settings) { callWebHookOf(repository.owner, repository.name, WebHook.Create, settings) {
for { for {
sender <- context.loginAccount sender <- Some(loginAccount)
owner <- getAccountByUserName(repository.owner) owner <- getAccountByUserName(repository.owner)
} yield { } yield {
WebHookCreatePayload( WebHookCreatePayload(
@@ -584,12 +646,13 @@ trait RepositoryViewerControllerBase extends ControllerBase {
requestBranch: String, requestBranch: String,
commitIdFrom: String, commitIdFrom: String,
commitIdTo: String, commitIdTo: String,
commitMessage: Option[String] commitMessage: Option[String],
loginAccount: Account
): Int = { ): Int = {
val issueId = insertIssue( val issueId = insertIssue(
owner = repository.owner, owner = repository.owner,
repository = repository.name, repository = repository.name,
loginUser = context.loginAccount.get.userName, loginUser = loginAccount.userName,
title = requestBranch, title = requestBranch,
content = commitMessage, content = commitMessage,
assignedUserName = None, assignedUserName = None,
@@ -607,7 +670,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
commitIdFrom = commitIdFrom, commitIdFrom = commitIdFrom,
commitIdTo = commitIdTo, commitIdTo = commitIdTo,
isDraft = false, isDraft = false,
loginAccount = context.loginAccount.get, loginAccount = loginAccount,
settings = context.settings settings = context.settings
) )
issueId issueId
@@ -720,26 +783,24 @@ trait RepositoryViewerControllerBase extends ControllerBase {
try { try {
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) {
git => git =>
defining(JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))) { val revCommit = JGitUtil.getRevCommitFromId(git, git.getRepository.resolve(id))
revCommit => val diffs = JGitUtil.getDiffs(git, None, id, true, false)
val diffs = JGitUtil.getDiffs(git, None, id, true, false) val oldCommitId = JGitUtil.getParentCommitId(git, id)
val oldCommitId = JGitUtil.getParentCommitId(git, id)
html.commit( html.commit(
id, id,
new JGitUtil.CommitInfo(revCommit), new JGitUtil.CommitInfo(revCommit),
JGitUtil.getBranchesOfCommit(git, revCommit.getName), JGitUtil.getBranchesOfCommit(git, revCommit.getName),
JGitUtil.getTagsOfCommit(git, revCommit.getName), JGitUtil.getTagsOfCommit(git, revCommit.getName),
getCommitStatusWithSummary(repository.owner, repository.name, revCommit.getName), getCommitStatusWithSummary(repository.owner, repository.name, revCommit.getName),
getCommitComments(repository.owner, repository.name, id, true), getCommitComments(repository.owner, repository.name, id, true),
repository, repository,
diffs, diffs,
oldCommitId, oldCommitId,
hasDeveloperRole(repository.owner, repository.name, context.loginAccount), hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
flash.get("info"), flash.get("info"),
flash.get("error") flash.get("error")
) )
}
} }
} catch { } catch {
case e: MissingObjectException => NotFound() case e: MissingObjectException => NotFound()
@@ -772,20 +833,22 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/commit/:id/comment/new", commentForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/commit/:id/comment/new", commentForm)(readableUsersOnly { (form, repository) =>
val id = params("id") context.withLoginAccount { loginAccount =>
createCommitComment( val id = params("id")
repository, createCommitComment(
id, repository,
context.loginAccount.get, id,
form.content, loginAccount,
form.fileName, form.content,
form.oldLineNumber, form.fileName,
form.newLineNumber, form.oldLineNumber,
form.diff, form.newLineNumber,
form.issueId form.diff,
) form.issueId
)
redirect(s"/${repository.owner}/${repository.name}/commit/${id}") redirect(s"/${repository.owner}/${repository.name}/commit/${id}")
}
}) })
ajaxGet("/:owner/:repository/commit/:id/comment/_form")(readableUsersOnly { repository => ajaxGet("/:owner/:repository/commit/:id/comment/_form")(readableUsersOnly { repository =>
@@ -807,72 +870,77 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}) })
ajaxPost("/:owner/:repository/commit/:id/comment/_data/new", commentForm)(readableUsersOnly { (form, repository) => ajaxPost("/:owner/:repository/commit/:id/comment/_data/new", commentForm)(readableUsersOnly { (form, repository) =>
val id = params("id") context.withLoginAccount {
val commentId = createCommitComment( loginAccount =>
repository, val id = params("id")
id, val commentId = createCommitComment(
context.loginAccount.get, repository,
form.content, id,
form.fileName, loginAccount,
form.oldLineNumber, form.content,
form.newLineNumber, form.fileName,
form.diff, form.oldLineNumber,
form.issueId form.newLineNumber,
) form.diff,
form.issueId
)
val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get val comment = getCommitComment(repository.owner, repository.name, commentId.toString).get
helper.html helper.html
.commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository) .commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
}
}) })
ajaxGet("/:owner/:repository/commit_comments/_data/:id")(readableUsersOnly { repository => ajaxGet("/:owner/:repository/commit_comments/_data/:id")(readableUsersOnly { repository =>
getCommitComment(repository.owner, repository.name, params("id")) map { context.withLoginAccount {
x => loginAccount =>
if (isEditable(x.userName, x.repositoryName, x.commentedUserName)) { getCommitComment(repository.owner, repository.name, params("id")) map {
params.get("dataType") collect { x =>
case t if t == "html" => html.editcomment(x.content, x.commentId, repository) if (isEditable(x.userName, x.repositoryName, x.commentedUserName, loginAccount)) {
} getOrElse { params.get("dataType") collect {
contentType = formats("json") case t if t == "html" => html.editcomment(x.content, x.commentId, repository)
org.json4s.jackson.Serialization.write( } getOrElse {
Map( contentType = formats("json")
"content" -> view.Markdown.toHtml( org.json4s.jackson.Serialization.write(
markdown = x.content, Map(
repository = repository, "content" -> view.Markdown.toHtml(
branch = repository.repository.defaultBranch, markdown = x.content,
enableWikiLink = false, repository = repository,
enableRefsLink = true, branch = repository.repository.defaultBranch,
enableAnchor = true, enableWikiLink = false,
enableLineBreaks = true, enableRefsLink = true,
enableTaskList = true, enableAnchor = true,
hasWritePermission = true enableLineBreaks = true,
enableTaskList = true,
hasWritePermission = true
)
)
) )
) }
) } else Unauthorized()
} } getOrElse NotFound()
} else Unauthorized() }
} getOrElse NotFound()
}) })
ajaxPost("/:owner/:repository/commit_comments/edit/:id", commentForm)(readableUsersOnly { (form, repository) => ajaxPost("/:owner/:repository/commit_comments/edit/:id", commentForm)(readableUsersOnly { (form, repository) =>
defining(repository.owner, repository.name) { context.withLoginAccount {
case (owner, name) => loginAccount =>
getCommitComment(owner, name, params("id")).map { comment => getCommitComment(repository.owner, repository.name, params("id")).map { comment =>
if (isEditable(owner, name, comment.commentedUserName)) { if (isEditable(repository.owner, repository.name, comment.commentedUserName, loginAccount)) {
updateCommitComment(comment.commentId, form.content) updateCommitComment(comment.commentId, form.content)
redirect(s"/${owner}/${name}/commit_comments/_data/${comment.commentId}") redirect(s"/${repository.owner}/${repository.name}/commit_comments/_data/${comment.commentId}")
} else Unauthorized() } else Unauthorized()
} getOrElse NotFound() } getOrElse NotFound()
} }
}) })
ajaxPost("/:owner/:repository/commit_comments/delete/:id")(readableUsersOnly { repository => ajaxPost("/:owner/:repository/commit_comments/delete/:id")(readableUsersOnly { repository =>
defining(repository.owner, repository.name) { context.withLoginAccount { loginAccount =>
case (owner, name) => getCommitComment(repository.owner, repository.name, params("id")).map { comment =>
getCommitComment(owner, name, params("id")).map { comment => if (isEditable(repository.owner, repository.name, comment.commentedUserName, loginAccount)) {
if (isEditable(owner, name, comment.commentedUserName)) { Ok(deleteCommitComment(comment.commentId))
Ok(deleteCommitComment(comment.commentId)) } else Unauthorized()
} else Unauthorized() } getOrElse NotFound()
} getOrElse NotFound()
} }
}) })
@@ -995,16 +1063,19 @@ trait RepositoryViewerControllerBase extends ControllerBase {
* Deletes branch. * Deletes branch.
*/ */
get("/:owner/:repository/delete/*")(writableUsersOnly { repository => get("/:owner/:repository/delete/*")(writableUsersOnly { repository =>
val branchName = multiParams("splat").head context.withLoginAccount {
val userName = context.loginAccount.get.userName loginAccount =>
if (repository.repository.defaultBranch != branchName) { val branchName = multiParams("splat").head
Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git => if (repository.repository.defaultBranch != branchName) {
git.branchDelete().setForce(true).setBranchNames(branchName).call() Using.resource(Git.open(getRepositoryDir(repository.owner, repository.name))) { git =>
val deleteBranchInfo = DeleteBranchInfo(repository.owner, repository.name, userName, branchName) git.branchDelete().setForce(true).setBranchNames(branchName).call()
recordActivity(deleteBranchInfo) val deleteBranchInfo =
} DeleteBranchInfo(repository.owner, repository.name, loginAccount.userName, branchName)
recordActivity(deleteBranchInfo)
}
}
redirect(s"/${repository.owner}/${repository.name}/branches")
} }
redirect(s"/${repository.owner}/${repository.name}/branches")
}) })
/** /**
@@ -1090,54 +1161,53 @@ trait RepositoryViewerControllerBase extends ControllerBase {
// get specified commit // get specified commit
JGitUtil.getDefaultBranch(git, repository, revstr).map { JGitUtil.getDefaultBranch(git, repository, revstr).map {
case (objectId, revision) => case (objectId, revision) =>
defining(JGitUtil.getRevCommitFromId(git, objectId)) { revCommit => val revCommit = JGitUtil.getRevCommitFromId(git, objectId)
val lastModifiedCommit = val lastModifiedCommit =
if (path == ".") revCommit else JGitUtil.getLastModifiedCommit(git, revCommit, path) if (path == ".") revCommit else JGitUtil.getLastModifiedCommit(git, revCommit, path)
val commitCount = JGitUtil.getCommitCount(git, lastModifiedCommit.getName) val commitCount = JGitUtil.getCommitCount(git, lastModifiedCommit.getName)
// get files // get files
val files = JGitUtil.getFileList( val files = JGitUtil.getFileList(
git, git,
revision, revision,
path, path,
context.settings.baseUrl, context.settings.baseUrl,
commitCount, commitCount,
context.settings.repositoryViewer.maxFiles context.settings.repositoryViewer.maxFiles
) )
val parentPath = if (path == ".") Nil else path.split("/").toList val parentPath = if (path == ".") Nil else path.split("/").toList
// process README // process README
val readme = files // files should be sorted alphabetically. val readme = files // files should be sorted alphabetically.
.find { file => .find { file =>
!file.isDirectory && RepositoryService.readmeFiles.contains(file.name.toLowerCase) !file.isDirectory && RepositoryService.readmeFiles.contains(file.name.toLowerCase)
} }
.map { file => .map { file =>
val path = (file.name :: parentPath.reverse).reverse val path = (file.name :: parentPath.reverse).reverse
path -> StringUtil.convertFromByteArray( path -> StringUtil.convertFromByteArray(
JGitUtil JGitUtil
.getContentFromId(Git.open(getRepositoryDir(repository.owner, repository.name)), file.id, true) .getContentFromId(Git.open(getRepositoryDir(repository.owner, repository.name)), file.id, true)
.get .get
) )
} }
html.files( html.files(
revision, revision,
repository, repository,
if (path == ".") Nil else path.split("/").toList, // current path if (path == ".") Nil else path.split("/").toList, // current path
new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit
getCommitStatusWithSummary(repository.owner, repository.name, lastModifiedCommit.getName), getCommitStatusWithSummary(repository.owner, repository.name, lastModifiedCommit.getName),
commitCount, commitCount,
files, files,
readme, readme,
hasDeveloperRole(repository.owner, repository.name, context.loginAccount), hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
getPullRequestFromBranch( getPullRequestFromBranch(
repository.owner, repository.owner,
repository.name, repository.name,
revstr, revstr,
repository.repository.defaultBranch repository.repository.defaultBranch
), ),
flash.get("info"), flash.get("info"),
flash.get("error") flash.get("error")
) )
}
} getOrElse NotFound() } getOrElse NotFound()
} }
} }
@@ -1257,8 +1327,9 @@ trait RepositoryViewerControllerBase extends ControllerBase {
} }
} }
private def isEditable(owner: String, repository: String, author: String)(implicit context: Context): Boolean = private def isEditable(owner: String, repository: String, author: String, loginAccount: Account): Boolean = {
hasDeveloperRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName hasDeveloperRole(owner, repository, Some(loginAccount)) || author == loginAccount.userName
}
private def conflict: Constraint = new Constraint() { private def conflict: Constraint = new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = { override def validate(name: String, value: String, messages: Messages): Option[String] = {

View File

@@ -9,7 +9,6 @@ import gitbucket.core.service.{AccountService, RepositoryService}
import gitbucket.core.ssh.SshServer import gitbucket.core.ssh.SshServer
import gitbucket.core.util.Implicits._ import gitbucket.core.util.Implicits._
import gitbucket.core.util.StringUtil._ import gitbucket.core.util.StringUtil._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.{AdminAuthenticator, Mailer} import gitbucket.core.util.{AdminAuthenticator, Mailer}
import org.apache.commons.io.IOUtils import org.apache.commons.io.IOUtils
import org.apache.commons.mail.EmailException import org.apache.commons.mail.EmailException
@@ -463,31 +462,28 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
}) })
get("/admin/users/:groupName/_editgroup")(adminOnly { get("/admin/users/:groupName/_editgroup")(adminOnly {
defining(params("groupName")) { groupName => val groupName = params("groupName")
html.usergroup(getAccountByUserName(groupName, true), getGroupMembers(groupName)) html.usergroup(getAccountByUserName(groupName, true), getGroupMembers(groupName))
}
}) })
post("/admin/users/:groupName/_editgroup", editGroupForm)(adminOnly { form => post("/admin/users/:groupName/_editgroup", editGroupForm)(adminOnly { form =>
defining( val groupName = params("groupName")
params("groupName"), val members = form.members
form.members .split(",")
.split(",") .map {
.map { _.split(":") match {
_.split(":") match { case Array(userName, isManager) => (userName, isManager.toBoolean)
case Array(userName, isManager) => (userName, isManager.toBoolean)
}
} }
.toList }
) { .toList
case (groupName, members) =>
getAccountByUserName(groupName, true).map {
account =>
updateGroup(groupName, form.description, form.url, form.isRemoved)
if (form.isRemoved) { getAccountByUserName(groupName, true).map {
// Remove from GROUP_MEMBER account =>
updateGroupMembers(form.groupName, Nil) updateGroup(groupName, form.description, form.url, form.isRemoved)
if (form.isRemoved) {
// Remove from GROUP_MEMBER
updateGroupMembers(form.groupName, Nil)
// // Remove repositories // // Remove repositories
// getRepositoryNamesOfUser(form.groupName).foreach { repositoryName => // getRepositoryNamesOfUser(form.groupName).foreach { repositoryName =>
// deleteRepository(groupName, repositoryName) // deleteRepository(groupName, repositoryName)
@@ -495,9 +491,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
// FileUtils.deleteDirectory(getWikiRepositoryDir(groupName, repositoryName)) // FileUtils.deleteDirectory(getWikiRepositoryDir(groupName, repositoryName))
// FileUtils.deleteDirectory(getTemporaryDir(groupName, repositoryName)) // FileUtils.deleteDirectory(getTemporaryDir(groupName, repositoryName))
// } // }
} else { } else {
// Update GROUP_MEMBER // Update GROUP_MEMBER
updateGroupMembers(form.groupName, members) updateGroupMembers(form.groupName, members)
// // Update COLLABORATOR for group repositories // // Update COLLABORATOR for group repositories
// getRepositoryNamesOfUser(form.groupName).foreach { repositoryName => // getRepositoryNamesOfUser(form.groupName).foreach { repositoryName =>
// removeCollaborators(form.groupName, repositoryName) // removeCollaborators(form.groupName, repositoryName)
@@ -505,13 +501,12 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
// addCollaborator(form.groupName, repositoryName, userName) // addCollaborator(form.groupName, repositoryName, userName)
// } // }
// } // }
} }
updateImage(form.groupName, form.fileId, form.clearImage) updateImage(form.groupName, form.fileId, form.clearImage)
redirect("/admin/users") redirect("/admin/users")
} getOrElse NotFound() } getOrElse NotFound()
}
}) })
get("/admin/data")(adminOnly { get("/admin/data")(adminOnly {
@@ -559,12 +554,11 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
protected def disableByNotYourself(paramName: String): Constraint = protected def disableByNotYourself(paramName: String): Constraint =
new Constraint() { new Constraint() {
override def validate(name: String, value: String, messages: Messages): Option[String] = { override def validate(name: String, value: String, messages: Messages): Option[String] = {
params.get(paramName).flatMap { userName => for {
if (userName == context.loginAccount.get.userName && params.get("removed") == Some("true")) userName <- params.get(paramName)
Some("You can't disable your account yourself") loginAccount <- context.loginAccount
else if userName == loginAccount.userName && params.get("removed") == Some("true")
None } yield "You can't disable your account yourself"
}
} }
} }

View File

@@ -136,32 +136,38 @@ trait WikiControllerBase extends ControllerBase {
}) })
get("/:owner/:repository/wiki/:page/_revert/:commitId")(readableUsersOnly { repository => get("/:owner/:repository/wiki/:page/_revert/:commitId")(readableUsersOnly { repository =>
if (isEditable(repository)) { context.withLoginAccount {
val pageName = StringUtil.urlDecode(params("page")) loginAccount =>
val Array(from, to) = params("commitId").split("\\.\\.\\.") 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))) { if (revertWikiPage(repository.owner, repository.name, from, to, loginAccount, Some(pageName))) {
redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}") redirect(s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}")
} else { } else {
flash.update("info", "This patch was not able to be reversed.") flash.update("info", "This patch was not able to be reversed.")
redirect( redirect(
s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_compare/${from}...${to}" s"/${repository.owner}/${repository.name}/wiki/${StringUtil.urlEncode(pageName)}/_compare/${from}...${to}"
) )
} }
} else Unauthorized() } else Unauthorized()
}
}) })
get("/:owner/:repository/wiki/_revert/:commitId")(readableUsersOnly { repository => get("/:owner/:repository/wiki/_revert/:commitId")(readableUsersOnly { repository =>
if (isEditable(repository)) { context.withLoginAccount {
val Array(from, to) = params("commitId").split("\\.\\.\\.") loginAccount =>
if (isEditable(repository)) {
val Array(from, to) = params("commitId").split("\\.\\.\\.")
if (revertWikiPage(repository.owner, repository.name, from, to, context.loginAccount.get, None)) { if (revertWikiPage(repository.owner, repository.name, from, to, loginAccount, None)) {
redirect(s"/${repository.owner}/${repository.name}/wiki") redirect(s"/${repository.owner}/${repository.name}/wiki")
} else { } else {
flash.update("info", "This patch was not able to be reversed.") flash.update("info", "This patch was not able to be reversed.")
redirect(s"/${repository.owner}/${repository.name}/wiki/_compare/${from}...${to}") redirect(s"/${repository.owner}/${repository.name}/wiki/_compare/${from}...${to}")
} }
} else Unauthorized() } else Unauthorized()
}
}) })
get("/:owner/:repository/wiki/:page/_edit")(readableUsersOnly { repository => get("/:owner/:repository/wiki/:page/_edit")(readableUsersOnly { repository =>
@@ -172,9 +178,9 @@ trait WikiControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/wiki/_edit", editForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/wiki/_edit", editForm)(readableUsersOnly { (form, repository) =>
if (isEditable(repository)) { context.withLoginAccount {
defining(context.loginAccount.get) { loginAccount =>
loginAccount => if (isEditable(repository)) {
saveWikiPage( saveWikiPage(
repository.owner, repository.owner,
repository.name, repository.name,
@@ -201,8 +207,8 @@ trait WikiControllerBase extends ControllerBase {
} else { } else {
redirect(s"/${repository.owner}/${repository.name}/wiki") redirect(s"/${repository.owner}/${repository.name}/wiki")
} }
} } else Unauthorized()
} else Unauthorized() }
}) })
get("/:owner/:repository/wiki/_new")(readableUsersOnly { repository => get("/:owner/:repository/wiki/_new")(readableUsersOnly { repository =>
@@ -212,9 +218,9 @@ trait WikiControllerBase extends ControllerBase {
}) })
post("/:owner/:repository/wiki/_new", newForm)(readableUsersOnly { (form, repository) => post("/:owner/:repository/wiki/_new", newForm)(readableUsersOnly { (form, repository) =>
if (isEditable(repository)) { context.withLoginAccount {
defining(context.loginAccount.get) { loginAccount =>
loginAccount => if (isEditable(repository)) {
saveWikiPage( saveWikiPage(
repository.owner, repository.owner,
repository.name, repository.name,
@@ -242,16 +248,15 @@ trait WikiControllerBase extends ControllerBase {
} else { } else {
redirect(s"/${repository.owner}/${repository.name}/wiki") redirect(s"/${repository.owner}/${repository.name}/wiki")
} }
} } else Unauthorized()
} else Unauthorized() }
}) })
get("/:owner/:repository/wiki/:page/_delete")(readableUsersOnly { repository => get("/:owner/:repository/wiki/:page/_delete")(readableUsersOnly { repository =>
if (isEditable(repository)) { context.withLoginAccount {
val pageName = StringUtil.urlDecode(params("page")) loginAccount =>
if (isEditable(repository)) {
defining(context.loginAccount.get) { val pageName = StringUtil.urlDecode(params("page"))
loginAccount =>
deleteWikiPage( deleteWikiPage(
repository.owner, repository.owner,
repository.name, repository.name,
@@ -270,8 +275,8 @@ trait WikiControllerBase extends ControllerBase {
updateLastActivityDate(repository.owner, repository.name) updateLastActivityDate(repository.owner, repository.name)
redirect(s"/${repository.owner}/${repository.name}/wiki") redirect(s"/${repository.owner}/${repository.name}/wiki")
} } else Unauthorized()
} else Unauthorized() }
}) })
get("/:owner/:repository/wiki/_pages")(referrersOnly { repository => get("/:owner/:repository/wiki/_pages")(referrersOnly { repository =>

View File

@@ -1,12 +1,11 @@
package gitbucket.core.util package gitbucket.core.util
import scala.language.reflectiveCalls
/** /**
* Provides control facilities. * Provides control facilities.
*/ */
object SyntaxSugars { object SyntaxSugars {
@deprecated("Use scala.util.Try instead", "4.36.0")
def defining[A, B](value: A)(f: A => B): B = f(value) def defining[A, B](value: A)(f: A => B): B = f(value)
@deprecated("Use scala.util.Try instead", "4.36.0") @deprecated("Use scala.util.Try instead", "4.36.0")