mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 21:45:50 +01:00
(refs #241)Work for specifying group manager
This commit is contained in:
1
src/main/resources/update/1_12.sql
Normal file
1
src/main/resources/update/1_12.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE GROUP_MEMBER ADD COLUMN MANAGER BOOLEAN DEFAULT FALSE;
|
||||
@@ -53,8 +53,8 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
// Members
|
||||
case "members" if(account.isGroupAccount) => {
|
||||
val members = getGroupMembers(account.userName)
|
||||
_root_.account.html.members(account, members,
|
||||
context.loginAccount.exists(x => members.contains(x.userName)))
|
||||
_root_.account.html.members(account, members.map(_._1),
|
||||
context.loginAccount.exists(x => members.exists { case (userName, isManager) => userName == x.userName && isManager }))
|
||||
}
|
||||
|
||||
// Repositories
|
||||
@@ -63,7 +63,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
|
||||
_root_.account.html.repositories(account,
|
||||
if(account.isGroupAccount) Nil else getGroupsByUserName(userName),
|
||||
getVisibleRepositories(context.loginAccount, baseUrl, Some(userName)),
|
||||
context.loginAccount.exists(x => members.contains(x.userName)))
|
||||
context.loginAccount.exists(x => members.exists { case (userName, isManager) => userName == x.userName && isManager }))
|
||||
}
|
||||
}
|
||||
} getOrElse NotFound
|
||||
|
||||
@@ -13,14 +13,14 @@ import org.apache.commons.io.FileUtils
|
||||
|
||||
class CreateController extends CreateControllerBase
|
||||
with RepositoryService with AccountService with WikiService with LabelsService with ActivityService
|
||||
with UsersAuthenticator with ReadableUsersAuthenticator with GroupMemberAuthenticator
|
||||
with UsersAuthenticator with ReadableUsersAuthenticator with GroupManagerAuthenticator
|
||||
|
||||
/**
|
||||
* Creates new repository or group.
|
||||
*/
|
||||
trait CreateControllerBase extends AccountManagementControllerBase {
|
||||
self: RepositoryService with AccountService with WikiService with LabelsService with ActivityService
|
||||
with UsersAuthenticator with ReadableUsersAuthenticator with GroupMemberAuthenticator =>
|
||||
with UsersAuthenticator with ReadableUsersAuthenticator with GroupManagerAuthenticator =>
|
||||
|
||||
case class RepositoryCreationForm(owner: String, name: String, description: Option[String],
|
||||
isPrivate: Boolean, createReadme: Boolean)
|
||||
@@ -84,7 +84,7 @@ trait CreateControllerBase extends AccountManagementControllerBase {
|
||||
|
||||
// Add collaborators for group repository
|
||||
if(ownerAccount.isGroupAccount){
|
||||
getGroupMembers(form.owner).foreach { userName =>
|
||||
getGroupMembers(form.owner).foreach { case (userName, isManager) =>
|
||||
addCollaborator(form.owner, form.name, userName)
|
||||
}
|
||||
}
|
||||
@@ -202,19 +202,27 @@ trait CreateControllerBase extends AccountManagementControllerBase {
|
||||
|
||||
post("/groups/new", newGroupForm)(usersOnly { form =>
|
||||
createGroup(form.groupName, form.url)
|
||||
updateGroupMembers(form.groupName, form.memberNames.map(_.split(",").toList).getOrElse(Nil))
|
||||
updateGroupMembers(form.groupName, form.memberNames.map(_.split(",").map {
|
||||
_.split(":") match {
|
||||
case Array(userName, isManager) => (userName, isManager.toBoolean)
|
||||
}
|
||||
}.toList).getOrElse(Nil))
|
||||
updateImage(form.groupName, form.fileId, false)
|
||||
redirect(s"/${form.groupName}")
|
||||
})
|
||||
|
||||
get("/:groupName/_edit")(membersOnly {
|
||||
get("/:groupName/_edit")(managersOnly {
|
||||
defining(params("groupName")){ groupName =>
|
||||
html.group(getAccountByUserName(groupName, true), getGroupMembers(groupName))
|
||||
}
|
||||
})
|
||||
|
||||
post("/:groupName/_edit", editGroupForm)(membersOnly { form =>
|
||||
defining(params("groupName"), form.memberNames.map(_.split(",").toList).getOrElse(Nil)){ case (groupName, memberNames) =>
|
||||
post("/:groupName/_edit", editGroupForm)(managersOnly { form =>
|
||||
defining(params("groupName"), form.memberNames.map(_.split(",").map {
|
||||
_.split(":") match {
|
||||
case Array(userName, isManager) => (userName, isManager.toBoolean)
|
||||
}
|
||||
}.toList).getOrElse(Nil)){ case (groupName, members) =>
|
||||
getAccountByUserName(groupName, true).map { account =>
|
||||
updateGroup(groupName, form.url, form.isRemoved)
|
||||
|
||||
@@ -230,11 +238,11 @@ trait CreateControllerBase extends AccountManagementControllerBase {
|
||||
}
|
||||
} else {
|
||||
// Update GROUP_MEMBER
|
||||
updateGroupMembers(form.groupName, memberNames)
|
||||
updateGroupMembers(form.groupName, members)
|
||||
// Update COLLABORATOR for group repositories
|
||||
getRepositoryNamesOfUser(form.groupName).foreach { repositoryName =>
|
||||
removeCollaborators(form.groupName, repositoryName)
|
||||
memberNames.foreach { userName =>
|
||||
members.foreach { case (userName, isManager) =>
|
||||
addCollaborator(form.groupName, repositoryName, userName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
val users = getAllUsers(includeRemoved)
|
||||
|
||||
val members = users.collect { case account if(account.isGroupAccount) =>
|
||||
account.userName -> getGroupMembers(account.userName)
|
||||
account.userName -> getGroupMembers(account.userName).map(_._1)
|
||||
}.toMap
|
||||
admin.users.html.list(users, members, includeRemoved)
|
||||
})
|
||||
@@ -127,7 +127,11 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
|
||||
post("/admin/users/_newgroup", newGroupForm)(adminOnly { form =>
|
||||
createGroup(form.groupName, form.url)
|
||||
updateGroupMembers(form.groupName, form.memberNames.map(_.split(",").toList).getOrElse(Nil))
|
||||
updateGroupMembers(form.groupName, form.memberNames.map(_.split(",").map {
|
||||
_.split(":") match {
|
||||
case Array(userName, isManager) => (userName, isManager.toBoolean)
|
||||
}
|
||||
}.toList).getOrElse(Nil))
|
||||
updateImage(form.groupName, form.fileId, false)
|
||||
redirect("/admin/users")
|
||||
})
|
||||
@@ -139,7 +143,11 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
})
|
||||
|
||||
post("/admin/users/:groupName/_editgroup", editGroupForm)(adminOnly { form =>
|
||||
defining(params("groupName"), form.memberNames.map(_.split(",").toList).getOrElse(Nil)){ case (groupName, memberNames) =>
|
||||
defining(params("groupName"), form.memberNames.map(_.split(",").map {
|
||||
_.split(":") match {
|
||||
case Array(userName, isManager) => (userName, isManager.toBoolean)
|
||||
}
|
||||
}.toList).getOrElse(Nil)){ case (groupName, members) =>
|
||||
getAccountByUserName(groupName, true).map { account =>
|
||||
updateGroup(groupName, form.url, form.isRemoved)
|
||||
|
||||
@@ -155,11 +163,11 @@ trait UserManagementControllerBase extends AccountManagementControllerBase {
|
||||
}
|
||||
} else {
|
||||
// Update GROUP_MEMBER
|
||||
updateGroupMembers(form.groupName, memberNames)
|
||||
updateGroupMembers(form.groupName, members)
|
||||
// Update COLLABORATOR for group repositories
|
||||
getRepositoryNamesOfUser(form.groupName).foreach { repositoryName =>
|
||||
removeCollaborators(form.groupName, repositoryName)
|
||||
memberNames.foreach { userName =>
|
||||
members.foreach { case (userName, isManager) =>
|
||||
addCollaborator(form.groupName, repositoryName, userName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,12 @@ import scala.slick.driver.H2Driver.simple._
|
||||
object GroupMembers extends Table[GroupMember]("GROUP_MEMBER") {
|
||||
def groupName = column[String]("GROUP_NAME", O PrimaryKey)
|
||||
def userName = column[String]("USER_NAME", O PrimaryKey)
|
||||
def * = groupName ~ userName <> (GroupMember, GroupMember.unapply _)
|
||||
def isManager = column[Boolean]("MANAGER")
|
||||
def * = groupName ~ userName ~ isManager <> (GroupMember, GroupMember.unapply _)
|
||||
}
|
||||
|
||||
case class GroupMember(
|
||||
groupName: String,
|
||||
userName: String
|
||||
userName: String,
|
||||
isManager: Boolean
|
||||
)
|
||||
@@ -122,18 +122,18 @@ trait AccountService {
|
||||
def updateGroup(groupName: String, url: Option[String], removed: Boolean): Unit =
|
||||
Accounts.filter(_.userName is groupName.bind).map(t => t.url.? ~ t.removed).update(url, removed)
|
||||
|
||||
def updateGroupMembers(groupName: String, members: List[String]): Unit = {
|
||||
def updateGroupMembers(groupName: String, members: List[(String, Boolean)]): Unit = {
|
||||
Query(GroupMembers).filter(_.groupName is groupName.bind).delete
|
||||
members.foreach { userName =>
|
||||
GroupMembers insert GroupMember (groupName, userName)
|
||||
members.foreach { case (userName, isManager) =>
|
||||
GroupMembers insert GroupMember (groupName, userName, isManager)
|
||||
}
|
||||
}
|
||||
|
||||
def getGroupMembers(groupName: String): List[String] =
|
||||
def getGroupMembers(groupName: String): List[(String, Boolean)] =
|
||||
Query(GroupMembers)
|
||||
.filter(_.groupName is groupName.bind)
|
||||
.sortBy(_.userName)
|
||||
.map(_.userName)
|
||||
.map(m => m.userName ~ m.isManager)
|
||||
.list
|
||||
|
||||
def getGroupsByUserName(userName: String): List[String] =
|
||||
|
||||
@@ -50,6 +50,7 @@ object AutoUpdate {
|
||||
* The history of versions. A head of this sequence is the current BitBucket version.
|
||||
*/
|
||||
val versions = Seq(
|
||||
Version(1, 12),
|
||||
Version(1, 11),
|
||||
Version(1, 10),
|
||||
Version(1, 9),
|
||||
|
||||
@@ -157,17 +157,17 @@ trait ReadableUsersAuthenticator { self: ControllerBase with RepositoryService =
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows only the group members.
|
||||
* Allows only the group managers.
|
||||
*/
|
||||
trait GroupMemberAuthenticator { self: ControllerBase with AccountService =>
|
||||
protected def membersOnly(action: => Any) = { authenticate(action) }
|
||||
protected def membersOnly[T](action: T => Any) = (form: T) => { authenticate(action(form)) }
|
||||
trait GroupManagerAuthenticator { self: ControllerBase with AccountService =>
|
||||
protected def managersOnly(action: => Any) = { authenticate(action) }
|
||||
protected def managersOnly[T](action: T => Any) = (form: T) => { authenticate(action(form)) }
|
||||
|
||||
private def authenticate(action: => Any) = {
|
||||
{
|
||||
defining(request.paths){ paths =>
|
||||
context.loginAccount match {
|
||||
case Some(x) if(getGroupMembers(paths(0)).contains(x.userName)) => action
|
||||
case Some(x) if(getGroupMembers(paths(0)).exists { case (userName, isManager) => userName == x.userName && isManager }) => action
|
||||
case _ => Unauthorized()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@(account: model.Account, groupNames: List[String], active: String,
|
||||
isGroupMember: Boolean = false)(body: Html)(implicit context: app.Context)
|
||||
isGroupManager: Boolean = false)(body: Html)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main(account.userName){
|
||||
@@ -42,7 +42,7 @@
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
@if(loginAccount.isDefined && account.isGroupAccount && isGroupMember){
|
||||
@if(loginAccount.isDefined && account.isGroupAccount && isGroupManager){
|
||||
<li class="pull-right">
|
||||
<div class="button-group">
|
||||
<a href="@url(account.userName)/_edit" class="btn">Edit Group</a>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@(account: model.Account, members: List[String], isGroupMember: Boolean)(implicit context: app.Context)
|
||||
@(account: model.Account, members: List[String], isGroupManager: Boolean)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@main(account, Nil, "members", isGroupMember){
|
||||
@main(account, Nil, "members", isGroupManager){
|
||||
@if(members.isEmpty){
|
||||
No members
|
||||
} else {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@(account: model.Account, groupNames: List[String],
|
||||
repositories: List[service.RepositoryService.RepositoryInfo],
|
||||
isGroupMember: Boolean)(implicit context: app.Context)
|
||||
isGroupManager: Boolean)(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@main(account, groupNames, "repositories", isGroupMember){
|
||||
@main(account, groupNames, "repositories", isGroupManager){
|
||||
@if(repositories.isEmpty){
|
||||
No repositories
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(account: Option[model.Account], members: List[String])(implicit context: app.Context)
|
||||
@(account: Option[model.Account], members: List[(String, Boolean)])(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@html.main(if(account.isEmpty) "New Group" else "Update Group"){
|
||||
@@ -35,7 +35,7 @@
|
||||
<fieldset>
|
||||
<label class="strong">Members</label>
|
||||
<ul id="members" class="collaborator">
|
||||
@members.map { userName =>
|
||||
@members.map { case (userName, isManager) =>
|
||||
<li data-name="@userName">
|
||||
<a href="@path/@url(userName)">@userName</a>
|
||||
<a href="#" class="remove">(remove)</a>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
@(account: Option[model.Account], members: List[String])(implicit context: app.Context)
|
||||
@(account: Option[model.Account], members: List[(String, Boolean)])(implicit context: app.Context)
|
||||
@import context._
|
||||
@import view.helpers._
|
||||
@main("Create a group"){
|
||||
@@ -35,8 +35,9 @@
|
||||
<fieldset>
|
||||
<label class="strong">Members</label>
|
||||
<ul id="members" class="collaborator">
|
||||
@members.map { userName =>
|
||||
@members.map { case (userName, isManager) =>
|
||||
<li data-name="@userName">
|
||||
<input type="checkbox" id="is_manager_@userName" @if(isManager){checked}/>
|
||||
<a href="@path/@url(userName)">@userName</a>
|
||||
<a href="#" class="remove">(remove)</a>
|
||||
</li>
|
||||
@@ -85,6 +86,7 @@ $(function(){
|
||||
// add member
|
||||
$('#members').append($('<li>')
|
||||
.data('name', userName)
|
||||
.append($('<input type="checkbox">').attr('id', 'is_manager_' + userName))
|
||||
.append($('<a>').attr('href', '@path/' + userName).text(userName))
|
||||
.append(' ')
|
||||
.append($('<a>').attr('href', '#').addClass('remove').text('(remove)')));
|
||||
@@ -92,7 +94,8 @@ $(function(){
|
||||
|
||||
// update hidden value
|
||||
var userNames = $('#members li').map(function(i, e){
|
||||
return $(e).data('name');
|
||||
var userName = $(e).data('name');
|
||||
return userName + ':' + $('#is_manager_' + userName).prop('checked');
|
||||
}).get().join(',');
|
||||
$('#memberNames').val(userNames);
|
||||
} else {
|
||||
@@ -107,7 +110,8 @@ $(function(){
|
||||
|
||||
// update hidden value
|
||||
var userNames = $('#members li').map(function(i, e){
|
||||
return $(e).data('name');
|
||||
var userName = $(e).data('name');
|
||||
return userName + ':' + $('#is_manager_' + userName).prop('checked');
|
||||
}).get().join(',');
|
||||
$('#memberNames').val(userNames);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user