Refactor new permission system

This commit is contained in:
Naoki Takezoe
2016-11-26 13:00:24 +09:00
parent 5b2e24daef
commit 6c6126148e
17 changed files with 103 additions and 81 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<changeSet>
<addColumn tableName="COLLABORATOR">
<column name="PERMISSION" type="varchar(10)" nullable="false" defaultValue="ADMIN"/>
<column name="ROLE" type="varchar(10)" nullable="false" defaultValue="ADMIN"/>
</addColumn>
<addColumn tableName="REPOSITORY">
<column name="WIKI_OPTION" type="varchar(10)" nullable="false" defaultValue="DISABLE"/>

View File

@@ -524,7 +524,7 @@ trait ApiControllerBase extends ControllerBase {
})
private def isEditable(owner: String, repository: String, author: String)(implicit context: Context): Boolean =
hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
hasDeveloperRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
}

View File

@@ -84,7 +84,7 @@ trait IssuesControllerBase extends ControllerBase {
getAssignableUserNames(owner, name),
getMilestones(owner, name),
getLabels(owner, name),
hasWritePermission(owner, name, context.loginAccount),
isManageable(repository),
repository)
}
} else Unauthorized()
@@ -386,7 +386,7 @@ trait IssuesControllerBase extends ControllerBase {
* Tests whether an logged-in user can manage issues.
*/
private def isManageable(repository: RepositoryInfo)(implicit context: Context): Boolean = {
hasWritePermission(repository.owner, repository.name, context.loginAccount)
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
}
/**
@@ -394,8 +394,9 @@ trait IssuesControllerBase extends ControllerBase {
*/
private def isEditable(repository: RepositoryInfo)(implicit context: Context): Boolean = {
repository.repository.options.issuesOption match {
case "PUBLIC" => hasReadPermission(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasWritePermission(repository.owner, repository.name, context.loginAccount)
case "ALL" => !repository.repository.isPrivate && context.loginAccount.isDefined
case "PUBLIC" => hasGuestRole(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
case "DISABLE" => false
}
}
@@ -404,7 +405,7 @@ trait IssuesControllerBase extends ControllerBase {
* Tests whether an issue or a comment is editable by a logged-in user.
*/
private def isEditableContent(owner: String, repository: String, author: String)(implicit context: Context): Boolean = {
hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
hasDeveloperRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
}
}

View File

@@ -29,7 +29,7 @@ trait LabelsControllerBase extends ControllerBase {
getLabels(repository.owner, repository.name),
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
})
ajaxGet("/:owner/:repository/issues/labels/new")(writableUsersOnly { repository =>
@@ -43,7 +43,7 @@ trait LabelsControllerBase extends ControllerBase {
// TODO futility
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
})
ajaxGet("/:owner/:repository/issues/labels/:labelId/edit")(writableUsersOnly { repository =>
@@ -59,7 +59,7 @@ trait LabelsControllerBase extends ControllerBase {
// TODO futility
countIssueGroupByLabels(repository.owner, repository.name, IssuesService.IssueSearchCondition(), Map.empty),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
})
ajaxPost("/:owner/:repository/issues/labels/:labelId/delete")(writableUsersOnly { repository =>

View File

@@ -27,7 +27,7 @@ trait MilestonesControllerBase extends ControllerBase {
params.getOrElse("state", "open"),
getMilestonesWithIssueCount(repository.owner, repository.name),
repository,
hasWritePermission(repository.owner, repository.name, context.loginAccount))
hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
})
get("/:owner/:repository/issues/milestones/new")(writableUsersOnly {

View File

@@ -115,7 +115,7 @@ trait PullRequestsControllerBase extends ControllerBase {
val hasConflict = LockUtil.lock(s"${owner}/${name}"){
checkConflict(owner, name, pullreq.branch, issueId)
}
val hasMergePermission = hasWritePermission(owner, name, context.loginAccount)
val hasMergePermission = hasDeveloperRole(owner, name, context.loginAccount)
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.branch)
val mergeStatus = PullRequestService.MergeStatus(
hasConflict = hasConflict,
@@ -125,7 +125,7 @@ trait PullRequestsControllerBase extends ControllerBase {
needStatusCheck = context.loginAccount.map{ u =>
branchProtection.needStatusCheck(u.userName)
}.getOrElse(true),
hasUpdatePermission = hasWritePermission(pullreq.requestUserName, pullreq.requestRepositoryName, context.loginAccount) &&
hasUpdatePermission = hasDeveloperRole(pullreq.requestUserName, pullreq.requestRepositoryName, context.loginAccount) &&
context.loginAccount.map{ u =>
!getProtectedBranchInfo(pullreq.requestUserName, pullreq.requestRepositoryName, pullreq.requestBranch).needStatusCheck(u.userName)
}.getOrElse(false),
@@ -163,7 +163,7 @@ trait PullRequestsControllerBase extends ControllerBase {
(issue, pullreq) <- getPullRequest(baseRepository.owner, baseRepository.name, issueId)
owner = pullreq.requestUserName
name = pullreq.requestRepositoryName
if hasWritePermission(owner, name, context.loginAccount)
if hasDeveloperRole(owner, name, context.loginAccount)
} yield {
val branchProtection = getProtectedBranchInfo(owner, name, pullreq.requestBranch)
if(branchProtection.needStatusCheck(loginAccount.userName)){
@@ -374,7 +374,7 @@ trait PullRequestsControllerBase extends ControllerBase {
forkedRepository,
originRepository,
forkedRepository,
hasWritePermission(originRepository.owner, originRepository.name, context.loginAccount),
hasDeveloperRole(originRepository.owner, originRepository.name, context.loginAccount),
getAssignableUserNames(originRepository.owner, originRepository.name),
getMilestones(originRepository.owner, originRepository.name),
getLabels(originRepository.owner, originRepository.name)
@@ -389,7 +389,7 @@ trait PullRequestsControllerBase extends ControllerBase {
}) getOrElse NotFound()
})
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(writableUsersOnly { forkedRepository =>
ajaxGet("/:owner/:repository/compare/*...*/mergecheck")(readableUsersOnly { forkedRepository =>
val Seq(origin, forked) = multiParams("splat")
val (originOwner, tmpOriginBranch) = parseCompareIdentifie(origin, forkedRepository.owner)
val (forkedOwner, tmpForkedBranch) = parseCompareIdentifie(forked, forkedRepository.owner)
@@ -544,7 +544,7 @@ trait PullRequestsControllerBase extends ControllerBase {
* Tests whether an logged-in user can manage pull requests.
*/
private def isManageable(repository: RepositoryInfo)(implicit context: Context): Boolean = {
hasWritePermission(repository.owner, repository.name, context.loginAccount)
hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
}
/**
@@ -552,8 +552,9 @@ trait PullRequestsControllerBase extends ControllerBase {
*/
private def isEditable(repository: RepositoryInfo)(implicit context: Context): Boolean = {
repository.repository.options.issuesOption match {
case "PUBLIC" => hasReadPermission(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasWritePermission(repository.owner, repository.name, context.loginAccount)
case "ALL" => !repository.repository.isPrivate && context.loginAccount.isDefined
case "PUBLIC" => hasGuestRole(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
case "DISABLE" => false
}
}

View File

@@ -179,8 +179,8 @@ trait RepositorySettingsControllerBase extends ControllerBase {
val collaborators = params("collaborators")
removeCollaborators(repository.owner, repository.name)
collaborators.split(",").withFilter(_.nonEmpty).map { collaborator =>
val userName :: permission :: Nil = collaborator.split(":").toList
addCollaborator(repository.owner, repository.name, userName, permission)
val userName :: role :: Nil = collaborator.split(":").toList
addCollaborator(repository.owner, repository.name, userName, role)
}
redirect(s"/${repository.owner}/${repository.name}/settings/collaborators")
})
@@ -416,7 +416,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
*/
private def featureOption: Constraint = new Constraint(){
override def validate(name: String, value: String, params: Map[String, String], messages: Messages): Option[String] =
if(Seq("DISABLE", "PRIVATE", "PUBLIC").contains(value)) None else Some("Option is invalid.")
if(Seq("DISABLE", "PRIVATE", "PUBLIC", "ALL").contains(value)) None else Some("Option is invalid.")
}

View File

@@ -110,7 +110,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
enableLineBreaks = params("enableLineBreaks").toBoolean,
enableTaskList = params("enableTaskList").toBoolean,
enableAnchor = false,
hasWritePermission = hasWritePermission(repository.owner, repository.name, context.loginAccount)
hasWritePermission = hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
)
})
@@ -151,7 +151,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
html.commits(if(path.isEmpty) Nil else path.split("/").toList, branchName, repository,
logs.splitWith{ (commit1, commit2) =>
view.helpers.date(commit1.commitTime) == view.helpers.date(commit2.commitTime)
}, page, hasNext, hasWritePermission(repository.owner, repository.name, context.loginAccount))
}, page, hasNext, hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
case Left(_) => NotFound()
}
}
@@ -275,7 +275,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
html.blob(id, repository, path.split("/").toList,
JGitUtil.getContentInfo(git, path, objectId),
new JGitUtil.CommitInfo(JGitUtil.getLastModifiedCommit(git, revCommit, path)),
hasWritePermission(repository.owner, repository.name, context.loginAccount),
hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
request.paths(2) == "blame")
}
} getOrElse NotFound()
@@ -329,7 +329,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
JGitUtil.getBranchesOfCommit(git, revCommit.getName),
JGitUtil.getTagsOfCommit(git, revCommit.getName),
getCommitComments(repository.owner, repository.name, id, false),
repository, diffs, oldCommitId, hasWritePermission(repository.owner, repository.name, context.loginAccount))
repository, diffs, oldCommitId, hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
}
}
}
@@ -358,7 +358,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
html.commentform(
commitId = id,
fileName, oldLineNumber, newLineNumber, issueId,
hasWritePermission = hasWritePermission(repository.owner, repository.name, context.loginAccount),
hasWritePermission = hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
repository = repository
)
})
@@ -374,7 +374,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
callPullRequestReviewCommentWebHook("create", comment, repository, issueId, context.baseUrl, context.loginAccount.get)
case None => recordCommentCommitActivity(repository.owner, repository.name, context.loginAccount.get.userName, id, form.content)
}
helper.html.commitcomment(comment, hasWritePermission(repository.owner, repository.name, context.loginAccount), repository)
helper.html.commitcomment(comment, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
})
ajaxGet("/:owner/:repository/commit_comments/_data/:id")(readableUsersOnly { repository =>
@@ -393,7 +393,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
enableRefsLink = true,
enableAnchor = true,
enableLineBreaks = true,
hasWritePermission = isEditable(x.userName, x.repositoryName, x.commentedUserName)
hasWritePermission = true
)
))
}
@@ -437,7 +437,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
.map(br => (br, getPullRequestByRequestCommit(repository.owner, repository.name, repository.repository.defaultBranch, br.name, br.commitId), protectedBranches.contains(br.name)))
.reverse
html.branches(branches, hasWritePermission(repository.owner, repository.name, context.loginAccount), repository)
html.branches(branches, hasDeveloperRole(repository.owner, repository.name, context.loginAccount), repository)
})
/**
@@ -547,7 +547,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
*/
private def fileList(repository: RepositoryService.RepositoryInfo, revstr: String = "", path: String = ".") = {
if(repository.commitCount == 0){
html.guide(repository, hasWritePermission(repository.owner, repository.name, context.loginAccount))
html.guide(repository, hasDeveloperRole(repository.owner, repository.name, context.loginAccount))
} else {
using(Git.open(getRepositoryDir(repository.owner, repository.name))){ git =>
// get specified commit
@@ -569,7 +569,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
html.files(revision, repository,
if(path == ".") Nil else path.split("/").toList, // current path
new JGitUtil.CommitInfo(lastModifiedCommit), // last modified commit
files, readme, hasWritePermission(repository.owner, repository.name, context.loginAccount),
files, readme, hasDeveloperRole(repository.owner, repository.name, context.loginAccount),
getPullRequestFromBranch(repository.owner, repository.name, revstr, repository.repository.defaultBranch),
flash.get("info"), flash.get("error"))
}
@@ -691,7 +691,7 @@ trait RepositoryViewerControllerBase extends ControllerBase {
}
private def isEditable(owner: String, repository: String, author: String)(implicit context: Context): Boolean =
hasWritePermission(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
hasDeveloperRole(owner, repository, context.loginAccount) || author == context.loginAccount.get.userName
override protected def renderUncaughtException(e: Throwable)(implicit request: HttpServletRequest, response: HttpServletResponse): Unit = {
e.printStackTrace()

View File

@@ -242,9 +242,9 @@ trait WikiControllerBase extends ControllerBase {
private def isEditable(repository: RepositoryInfo)(implicit context: Context): Boolean = {
repository.repository.options.wikiOption match {
// case "ALL" => repository.repository.isPrivate == false || hasReadPermission(repository.owner, repository.name, context.loginAccount)
case "PUBLIC" => hasReadPermission(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasWritePermission(repository.owner, repository.name, context.loginAccount)
case "ALL" => !repository.repository.isPrivate && context.loginAccount.isDefined
case "PUBLIC" => hasGuestRole(repository.owner, repository.name, context.loginAccount)
case "PRIVATE" => hasDeveloperRole(repository.owner, repository.name, context.loginAccount)
case "DISABLE" => false
}
}

View File

@@ -7,8 +7,8 @@ trait CollaboratorComponent extends TemplateComponent { self: Profile =>
class Collaborators(tag: Tag) extends Table[Collaborator](tag, "COLLABORATOR") with BasicTemplate {
val collaboratorName = column[String]("COLLABORATOR_NAME")
val permission = column[String]("PERMISSION")
def * = (userName, repositoryName, collaboratorName, permission) <> (Collaborator.tupled, Collaborator.unapply)
val role = column[String]("ROLE")
def * = (userName, repositoryName, collaboratorName, role) <> (Collaborator.tupled, Collaborator.unapply)
def byPrimaryKey(owner: String, repository: String, collaborator: String) =
byRepository(owner, repository) && (collaboratorName === collaborator.bind)
@@ -19,15 +19,15 @@ case class Collaborator(
userName: String,
repositoryName: String,
collaboratorName: String,
permission: String
role: String
)
sealed abstract class Permission(val name: String)
sealed abstract class Role(val name: String)
object Permission {
object ADMIN extends Permission("ADMIN")
object WRITE extends Permission("WRITE")
object READ extends Permission("READ")
object Role {
object ADMIN extends Role("ADMIN")
object DEVELOPER extends Role("DEVELOPER")
object GUEST extends Role("GUEST")
// val values: Vector[Permission] = Vector(ADMIN, WRITE, READ)
//

View File

@@ -434,7 +434,7 @@ trait IssuesService {
}
def getAssignableUserNames(owner: String, repository: String)(implicit s: Session): List[String] = {
(getCollaboratorUserNames(owner, repository, Seq(Permission.ADMIN, Permission.WRITE)) :::
(getCollaboratorUserNames(owner, repository, Seq(Role.ADMIN, Role.DEVELOPER)) :::
(if (getAccountByUserName(owner).get.isGroupAccount) getGroupMembers(owner).map(_.userName) else List(owner))).distinct.sorted
}

View File

@@ -1,7 +1,7 @@
package gitbucket.core.service
import gitbucket.core.controller.Context
import gitbucket.core.model.{Collaborator, Repository, RepositoryOptions, Account, Permission}
import gitbucket.core.model.{Collaborator, Repository, RepositoryOptions, Account, Role}
import gitbucket.core.model.Profile._
import gitbucket.core.util.JGitUtil
import profile.simple._
@@ -335,8 +335,8 @@ trait RepositoryService { self: AccountService =>
/**
* Add collaborator (user or group) to the repository.
*/
def addCollaborator(userName: String, repositoryName: String, collaboratorName: String, permission: String)(implicit s: Session): Unit =
Collaborators insert Collaborator(userName, repositoryName, collaboratorName, permission)
def addCollaborator(userName: String, repositoryName: String, collaboratorName: String, role: String)(implicit s: Session): Unit =
Collaborators insert Collaborator(userName, repositoryName, collaboratorName, role)
/**
* Remove all collaborators from the repository.
@@ -359,38 +359,38 @@ trait RepositoryService { self: AccountService =>
* Returns the list of all collaborator name and permission which is sorted with ascending order.
* If a group is added as a collaborator, this method returns users who are belong to that group.
*/
def getCollaboratorUserNames(userName: String, repositoryName: String, filter: Seq[Permission] = Nil)(implicit s: Session): List[String] = {
def getCollaboratorUserNames(userName: String, repositoryName: String, filter: Seq[Role] = Nil)(implicit s: Session): List[String] = {
val q1 = Collaborators
.innerJoin(Accounts).on { case (t1, t2) => (t1.collaboratorName === t2.userName) && (t2.groupAccount === false.bind) }
.filter { case (t1, t2) => t1.byRepository(userName, repositoryName) }
.map { case (t1, t2) => (t1.collaboratorName, t1.permission) }
.map { case (t1, t2) => (t1.collaboratorName, t1.role) }
val q2 = Collaborators
.innerJoin(Accounts).on { case (t1, t2) => (t1.collaboratorName === t2.userName) && (t2.groupAccount === true.bind) }
.innerJoin(GroupMembers).on { case ((t1, t2), t3) => t2.userName === t3.groupName }
.filter { case ((t1, t2), t3) => t1.byRepository(userName, repositoryName) }
.map { case ((t1, t2), t3) => (t3.userName, t1.permission) }
.map { case ((t1, t2), t3) => (t3.userName, t1.role) }
q1.union(q2).list.filter { x => filter.isEmpty || filter.exists(_.name == x._2) }.map(_._1)
}
def hasWritePermission(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = {
def hasDeveloperRole(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = {
loginAccount match {
case Some(a) if(a.isAdmin) => true
case Some(a) if(a.userName == owner) => true
case Some(a) if(getGroupMembers(owner).exists(_.userName == a.userName)) => true
case Some(a) if(getCollaboratorUserNames(owner, repository, Seq(Permission.ADMIN, Permission.WRITE)).contains(a.userName)) => true
case Some(a) if(getCollaboratorUserNames(owner, repository, Seq(Role.ADMIN, Role.DEVELOPER)).contains(a.userName)) => true
case _ => false
}
}
def hasReadPermission(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = {
def hasGuestRole(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = {
loginAccount match {
case Some(a) if(a.isAdmin) => true
case Some(a) if(a.userName == owner) => true
case Some(a) if(getGroupMembers(owner).exists(_.userName == a.userName)) => true
case Some(a) if(getCollaboratorUserNames(owner, repository, Seq(Permission.ADMIN, Permission.WRITE, Permission.READ)).contains(a.userName)) => true
case Some(a) if(getCollaboratorUserNames(owner, repository, Seq(Role.ADMIN, Role.DEVELOPER, Role.GUEST)).contains(a.userName)) => true
case _ => false
}
}

View File

@@ -84,7 +84,7 @@ class GitAuthenticationFilter extends Filter with RepositoryService with Account
Array(username, password) = AuthUtil.decodeAuthHeader(auth).split(":", 2)
account <- authenticate(settings, username, password)
} yield if(isUpdating || repository.repository.isPrivate){
if(hasWritePermission(repository.owner, repository.name, Some(account))){
if(hasDeveloperRole(repository.owner, repository.name, Some(account))){
request.setAttribute(Keys.Request.UserName, account.userName)
true
} else false

View File

@@ -92,7 +92,7 @@ abstract class DefaultGitCommand(val owner: String, val repoName: String) extend
protected def isWritableUser(username: String, repositoryInfo: RepositoryService.RepositoryInfo)
(implicit session: Session): Boolean =
getAccountByUserName(username) match {
case Some(account) => hasWritePermission(repositoryInfo.owner, repositoryInfo.name, Some(account))
case Some(account) => hasDeveloperRole(repositoryInfo.owner, repositoryInfo.name, Some(account))
case None => false
}

View File

@@ -2,13 +2,11 @@ package gitbucket.core.util
import gitbucket.core.controller.ControllerBase
import gitbucket.core.service.{AccountService, RepositoryService}
import gitbucket.core.model.Permission
import gitbucket.core.model.Role
import RepositoryService.RepositoryInfo
import Implicits._
import ControlUtil._
import scala.collection.Searching.search
/**
* Allows only oneself and administrators.
*/
@@ -45,7 +43,7 @@ trait OwnerAuthenticator { self: ControllerBase with RepositoryService with Acco
case Some(x) if(repository.owner == x.userName) => action(repository)
// TODO Repository management is allowed for only group managers?
case Some(x) if(getGroupMembers(repository.owner).exists { m => m.userName == x.userName && m.isManager == true }) => action(repository)
case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Permission.ADMIN)).contains(x.userName)) => action(repository)
case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Role.ADMIN)).contains(x.userName)) => action(repository)
case _ => Unauthorized()
}
} getOrElse NotFound()
@@ -156,7 +154,7 @@ trait WritableUsersAuthenticator { self: ControllerBase with RepositoryService w
case Some(x) if(x.isAdmin) => action(repository)
case Some(x) if(paths(0) == x.userName) => action(repository)
case Some(x) if(getGroupMembers(repository.owner).exists(_.userName == x.userName)) => action(repository)
case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Permission.ADMIN, Permission.WRITE)).contains(x.userName)) => action(repository)
case Some(x) if(getCollaboratorUserNames(paths(0), paths(1), Seq(Role.ADMIN, Role.DEVELOPER)).contains(x.userName)) => action(repository)
case _ => Unauthorized()
}
} getOrElse NotFound()

View File

@@ -2,7 +2,7 @@
isGroupRepository: Boolean,
repository: gitbucket.core.service.RepositoryService.RepositoryInfo)(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.view.helpers
@import gitbucket.core.model.Permission
@import gitbucket.core.model.Role
@gitbucket.core.html.main("Settings", Some(repository)){
@gitbucket.core.html.menu("settings", repository){
@gitbucket.core.settings.html.menu("collaborators", repository){
@@ -77,7 +77,8 @@ $(function(){
$.post('@context.path/_user/existence', { 'userName': userName },
function(data, status){
if(data != ''){
addListHTML(userName, '@Permission.ADMIN.name', '#' + id + '-list');
addListHTML(userName, '@Role.ADMIN.name', '#' + id + '-list');
$('#userName-' + id).val('');
} else {
$('#error-' + id).text('User does not exist.');
}
@@ -94,26 +95,26 @@ $(function(){
});
@collaborators.map { case (collaborator, isGroup) =>
addListHTML('@collaborator.collaboratorName', '@collaborator.permission', @if(isGroup){'#group-list'}else{'#collaborator-list'});
addListHTML('@collaborator.collaboratorName', '@collaborator.role', @if(isGroup){'#group-list'}else{'#collaborator-list'});
}
function addListHTML(userName, permission, id){
var adminButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Permission.ADMIN.name" name="' + userName + '">Admin</label>');
if(permission == '@Permission.ADMIN.name'){
function addListHTML(userName, role, id){
var adminButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.ADMIN.name" name="' + userName + '">Admin</label>');
if(role == '@Role.ADMIN.name'){
adminButton.addClass('active');
}
var writeButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Permission.WRITE.name" name="' + userName + '">Write</label>');
if(permission == '@Permission.WRITE.name'){
var writeButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.DEVELOPER.name" name="' + userName + '">Developer</label>');
if(role == '@Role.DEVELOPER.name'){
writeButton.addClass('active');
}
var readButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Permission.READ.name" name="' + userName + '">Read</label>');
if(permission == '@Permission.READ.name'){
var readButton = $('<label class="btn btn-default btn-mini"><input type="radio" value="@Role.GUEST.name" name="' + userName + '">Guest</label>');
if(role == '@Role.GUEST.name'){
readButton.addClass('active');
}
$(id).append($('<li>')
.data('name', userName)
.append($('<div class="btn-group permission" data-toggle="buttons">')
.append($('<div class="btn-group role" data-toggle="buttons">')
.append(adminButton)
.append(writeButton)
.append(readButton))

View File

@@ -61,12 +61,17 @@
</div>
<div class="radio">
<label>
<input type="radio" name="issuesOption" value="PRIVATE" @if(repository.repository.options.issuesOption == "PRIVATE"){ checked}> Writable users can view, create and comment on issues
<input type="radio" name="issuesOption" value="PRIVATE" @if(repository.repository.options.issuesOption == "PRIVATE"){ checked}> Developers can view, create and comment on issues
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="issuesOption" value="PUBLIC" @if(repository.repository.options.issuesOption == "PUBLIC"){ checked}> Readable users can view, create and comment on isues
<input type="radio" name="issuesOption" value="PUBLIC" @if(repository.repository.options.issuesOption == "PUBLIC"){ checked}> Developers and guests can view, create and comment on isues
</label>
</div>
<div class="radio for-public-repo">
<label>
<input type="radio" name="issuesOption" value="ALL" @if(repository.repository.options.issuesOption == "ALL"){ checked}> All users can view, create and comment on isues
</label>
</div>
<label for="externalIssuesUrl" class="strong">External URL:
@@ -87,12 +92,17 @@
</div>
<div class="radio">
<label>
<input type="radio" name="wikiOption" value="PRIVATE" @if(repository.repository.options.wikiOption == "PRIVATE"){ checked}> Writable users can view, create and edit wiki pages
<input type="radio" name="wikiOption" value="PRIVATE" @if(repository.repository.options.wikiOption == "PRIVATE"){ checked}> Developers can view, create and edit wiki pages
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="wikiOption" value="PUBLIC" @if(repository.repository.options.wikiOption == "PUBLIC"){ checked}> Readable users can view, create and edit wiki pages
<input type="radio" name="wikiOption" value="PUBLIC" @if(repository.repository.options.wikiOption == "PUBLIC"){ checked}> Developers ans guests can view, create and edit wiki pages
</label>
</div>
<div class="radio for-public-repo">
<label>
<input type="radio" name="wikiOption" value="ALL" @if(repository.repository.options.issuesOption == "ALL"){ checked}> All users can view, create and comment on isues
</label>
</div>
<label for="externalWikiUrl" class="strong">External URL:
@@ -112,14 +122,25 @@
<script>
$(function(){
updateFeatures();
$('input[name=issuesOption], input[name=wikiOption]').click(function(){
$('input[name=isPrivate], input[name=issuesOption], input[name=wikiOption]').click(function(){
updateFeatures();
});
});
function updateFeatures() {
$('#externalIssuesUrl').prop('disabled', !$('input[name=issuesOption]').select('[value=DISABLE]').prop('checked'));
$('#externalWikiUrl').prop('disabled', !$('input[name=wikiOption]').select('[value=DISABLE]').prop('checked'));
if($('input[name=isPrivate]:checked').val() == 'false'){
$('.for-public-repo').show();
} else {
if($('input[name=issuesOption]:checked').val() == 'ALL'){
$('input[name=issuesOption][value=PUBLIC]').prop('checked', true);
}
if($('input[name=wikiOption]:checked').val() == 'ALL'){
$('input[name=wikiOption][value=PUBLIC]').prop('checked', true);
}
$('.for-public-repo').hide();
}
$('#externalIssuesUrl').prop('disabled', $('input[name=issuesOption]:checked').val() != 'DISABLE');
$('#externalWikiUrl').prop('disabled', $('input[name=wikiOption]:checked').val() != 'DISABLE');
}
</script>