Compare commits

...

8 Commits

Author SHA1 Message Date
Naoki Takezoe
8a9588f17f Moving to Quill 2016-03-10 18:30:48 +09:00
Naoki Takezoe
682f3a4c10 Moving to Quill 2016-03-10 16:40:25 +09:00
Naoki Takezoe
dad29d93c2 Moving to Quill 2016-03-10 13:27:02 +09:00
Naoki Takezoe
fc99de8a65 Merge branch 'master' into quill
# Conflicts:
#	build.sbt
#	src/main/scala/gitbucket/core/controller/AccountController.scala
#	src/main/scala/gitbucket/core/controller/UserManagementController.scala
2016-03-10 01:51:35 +09:00
Naoki Takezoe
bc4af8e7c1 Finished to move AccountService to quill 2016-03-07 10:05:51 +09:00
Naoki Takezoe
cb3a79c9b3 Move some methods of AccountService to quill 2016-03-06 14:20:32 +09:00
Naoki Takezoe
b775ce157f Fix GroupMember model 2016-03-06 14:04:27 +09:00
Naoki Takezoe
cfcd250914 Introduction to quill 2016-03-03 18:36:52 +09:00
37 changed files with 408 additions and 339 deletions

View File

@@ -38,6 +38,7 @@ libraryDependencies ++= Seq(
"com.mchange" % "c3p0" % "0.9.5.2", "com.mchange" % "c3p0" % "0.9.5.2",
"com.typesafe" % "config" % "1.3.0", "com.typesafe" % "config" % "1.3.0",
"com.typesafe.akka" %% "akka-actor" % "2.3.14", "com.typesafe.akka" %% "akka-actor" % "2.3.14",
"io.getquill" %% "quill-jdbc" % "0.4.1",
"fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.0.0", "fr.brouillard.oss.security.xhub" % "xhub4j-core" % "1.0.0",
"com.enragedginger" %% "akka-quartz-scheduler" % "1.4.0-akka-2.3.x" exclude("c3p0","c3p0"), "com.enragedginger" %% "akka-quartz-scheduler" % "1.4.0-akka-2.3.x" exclude("c3p0","c3p0"),
"org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided", "org.eclipse.jetty" % "jetty-webapp" % JettyVersion % "provided",

View File

@@ -0,0 +1,8 @@
db.dataSourceClassName="org.h2.jdbcx.JdbcDataSource"
db.dataSource.url="jdbc:h2:~/.gitbucket/data;MVCC=true"
db.dataSource.user="sa"
db.dataSource.password="sa"
#db.dataSource.cachePrepStmts=true
#db.dataSource.prepStmtCacheSize=250
#db.dataSource.prepStmtCacheSqlLimit=2048
#db.connectionTimeout=30000

View File

@@ -39,7 +39,7 @@ object ApiRepository{
description = repository.description.getOrElse(""), description = repository.description.getOrElse(""),
watchers = 0, watchers = 0,
forks = forkedCount, forks = forkedCount,
`private` = repository.isPrivate, `private` = repository.`private`,
default_branch = repository.defaultBranch, default_branch = repository.defaultBranch,
owner = owner owner = owner
)(urlIsHtmlUrl) )(urlIsHtmlUrl)

View File

@@ -29,8 +29,8 @@ object ApiUser{
def apply(user: Account): ApiUser = ApiUser( def apply(user: Account): ApiUser = ApiUser(
login = user.userName, login = user.userName,
email = user.mailAddress, email = user.mailAddress,
`type` = if(user.isGroupAccount){ "Organization" }else{ "User" }, `type` = if(user.groupAccount){ "Organization" }else{ "User" },
site_admin = user.isAdmin, site_admin = user.administrator,
created_at = user.registeredDate created_at = user.registeredDate
) )
} }

View File

@@ -114,23 +114,23 @@ trait AccountControllerBase extends AccountManagementControllerBase {
// Public Activity // Public Activity
case "activity" => case "activity" =>
gitbucket.core.account.html.activity(account, gitbucket.core.account.html.activity(account,
if(account.isGroupAccount) Nil else getGroupsByUserName(userName), if(account.groupAccount) Nil else getGroupsByUserName(userName),
getActivitiesByUser(userName, true)) getActivitiesByUser(userName, true))
// Members // Members
case "members" if(account.isGroupAccount) => { case "members" if(account.groupAccount) => {
val members = getGroupMembers(account.userName) val members = getGroupMembers(account.userName)
gitbucket.core.account.html.members(account, members.map(_.userName), gitbucket.core.account.html.members(account, members.map(_.userName),
context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager })) context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.manager }))
} }
// Repositories // Repositories
case _ => { case _ => {
val members = getGroupMembers(account.userName) val members = getGroupMembers(account.userName)
gitbucket.core.account.html.repositories(account, gitbucket.core.account.html.repositories(account,
if(account.isGroupAccount) Nil else getGroupsByUserName(userName), if(account.groupAccount) Nil else getGroupsByUserName(userName),
getVisibleRepositories(context.loginAccount, Some(userName)), getVisibleRepositories(context.loginAccount, Some(userName)),
context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager })) context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.manager }))
} }
} }
} getOrElse NotFound } getOrElse NotFound
@@ -190,7 +190,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
// removeUserRelatedData(userName) // removeUserRelatedData(userName)
removeUserRelatedData(userName) removeUserRelatedData(userName)
updateAccount(account.copy(isRemoved = true)) updateAccount(account.copy(removed = true))
} }
session.invalidate session.invalidate
@@ -360,7 +360,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
case _: List[String] => case _: List[String] =>
val managerPermissions = groups.map { group => val managerPermissions = groups.map { group =>
val members = getGroupMembers(group) val members = getGroupMembers(group)
context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.isManager }) context.loginAccount.exists(x => members.exists { member => member.userName == x.userName && member.manager })
} }
helper.html.forkrepository( helper.html.forkrepository(
repository, repository,
@@ -389,7 +389,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
repositoryName = repository.name, repositoryName = repository.name,
userName = accountName, userName = accountName,
description = repository.repository.description, description = repository.repository.description,
isPrivate = repository.repository.isPrivate, isPrivate = repository.repository.`private`,
originRepositoryName = Some(originRepositoryName), originRepositoryName = Some(originRepositoryName),
originUserName = Some(originUserName), originUserName = Some(originUserName),
parentRepositoryName = Some(repository.name), parentRepositoryName = Some(repository.name),
@@ -398,7 +398,7 @@ trait AccountControllerBase extends AccountManagementControllerBase {
// Add collaborators for group repository // Add collaborators for group repository
val ownerAccount = getAccountByUserName(accountName).get val ownerAccount = getAccountByUserName(accountName).get
if(ownerAccount.isGroupAccount){ if(ownerAccount.groupAccount){
getGroupMembers(accountName).foreach { member => getGroupMembers(accountName).foreach { member =>
addCollaborator(accountName, repository.name, member.userName) addCollaborator(accountName, repository.name, member.userName)
} }

View File

@@ -50,7 +50,7 @@ abstract class ControllerBase extends ScalatraFilter
if(account == null){ if(account == null){
// Redirect to login form // Redirect to login form
httpResponse.sendRedirect(baseUrl + "/signin?redirect=" + StringUtil.urlEncode(path)) httpResponse.sendRedirect(baseUrl + "/signin?redirect=" + StringUtil.urlEncode(path))
} else if(account.isAdmin){ } else if(account.administrator){
// H2 Console (administrators only) // H2 Console (administrators only)
chain.doFilter(request, response) chain.doFilter(request, response)
} else { } else {

View File

@@ -110,7 +110,7 @@ trait IndexControllerBase extends ControllerBase {
get("/_user/proposals")(usersOnly { get("/_user/proposals")(usersOnly {
contentType = formats("json") contentType = formats("json")
org.json4s.jackson.Serialization.write( org.json4s.jackson.Serialization.write(
Map("options" -> getAllUsers(false).filter(!_.isGroupAccount).map(_.userName).toArray) Map("options" -> getAllUsers(false).filter(!_.groupAccount).map(_.userName).toArray)
) )
}) })

View File

@@ -67,7 +67,7 @@ trait IssuesControllerBase extends ControllerBase {
_, _,
getComments(owner, name, issueId.toInt), getComments(owner, name, issueId.toInt),
getIssueLabels(owner, name, issueId.toInt), getIssueLabels(owner, name, issueId.toInt),
(getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.isGroupAccount) Nil else List(owner))).sorted, (getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.groupAccount) Nil else List(owner))).sorted,
getMilestonesWithIssueCount(owner, name), getMilestonesWithIssueCount(owner, name),
getLabels(owner, name), getLabels(owner, name),
hasWritePermission(owner, name, context.loginAccount), hasWritePermission(owner, name, context.loginAccount),
@@ -79,7 +79,7 @@ trait IssuesControllerBase extends ControllerBase {
get("/:owner/:repository/issues/new")(readableUsersOnly { repository => get("/:owner/:repository/issues/new")(readableUsersOnly { repository =>
defining(repository.owner, repository.name){ case (owner, name) => defining(repository.owner, repository.name){ case (owner, name) =>
html.create( html.create(
(getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.isGroupAccount) Nil else List(owner))).sorted, (getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.groupAccount) Nil else List(owner))).sorted,
getMilestones(owner, name), getMilestones(owner, name),
getLabels(owner, name), getLabels(owner, name),
hasWritePermission(owner, name, context.loginAccount), hasWritePermission(owner, name, context.loginAccount),
@@ -380,7 +380,7 @@ trait IssuesControllerBase extends ControllerBase {
"issues", "issues",
searchIssue(condition, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName), searchIssue(condition, false, (page - 1) * IssueLimit, IssueLimit, owner -> repoName),
page, page,
if(!getAccountByUserName(owner).exists(_.isGroupAccount)){ if(!getAccountByUserName(owner).exists(_.groupAccount)){
(getCollaborators(owner, repoName) :+ owner).sorted (getCollaborators(owner, repoName) :+ owner).sorted
} else { } else {
getCollaborators(owner, repoName) getCollaborators(owner, repoName)

View File

@@ -94,7 +94,7 @@ trait PullRequestsControllerBase extends ControllerBase {
(commits.flatten.map(commit => getCommitComments(owner, name, commit.id, true)).flatten.toList ::: getComments(owner, name, issueId)) (commits.flatten.map(commit => getCommitComments(owner, name, commit.id, true)).flatten.toList ::: getComments(owner, name, issueId))
.sortWith((a, b) => a.registeredDate before b.registeredDate), .sortWith((a, b) => a.registeredDate before b.registeredDate),
getIssueLabels(owner, name, issueId), getIssueLabels(owner, name, issueId),
(getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.isGroupAccount) Nil else List(owner))).sorted, (getCollaborators(owner, name) ::: (if(getAccountByUserName(owner).get.groupAccount) Nil else List(owner))).sorted,
getMilestonesWithIssueCount(owner, name), getMilestonesWithIssueCount(owner, name),
getLabels(owner, name), getLabels(owner, name),
commits, commits,
@@ -370,7 +370,7 @@ trait PullRequestsControllerBase extends ControllerBase {
originRepository, originRepository,
forkedRepository, forkedRepository,
hasWritePermission(originRepository.owner, originRepository.name, context.loginAccount), hasWritePermission(originRepository.owner, originRepository.name, context.loginAccount),
(getCollaborators(originRepository.owner, originRepository.name) ::: (if(getAccountByUserName(originRepository.owner).get.isGroupAccount) Nil else List(originRepository.owner))).sorted, (getCollaborators(originRepository.owner, originRepository.name) ::: (if(getAccountByUserName(originRepository.owner).get.groupAccount) Nil else List(originRepository.owner))).sorted,
getMilestones(originRepository.owner, originRepository.name), getMilestones(originRepository.owner, originRepository.name),
getLabels(originRepository.owner, originRepository.name) getLabels(originRepository.owner, originRepository.name)
) )
@@ -524,7 +524,7 @@ trait PullRequestsControllerBase extends ControllerBase {
"pulls", "pulls",
searchIssue(condition, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName), searchIssue(condition, true, (page - 1) * PullRequestLimit, PullRequestLimit, owner -> repoName),
page, page,
if(!getAccountByUserName(owner).exists(_.isGroupAccount)){ if(!getAccountByUserName(owner).exists(_.groupAccount)){
(getCollaborators(owner, repoName) :+ owner).sorted (getCollaborators(owner, repoName) :+ owner).sorted
} else { } else {
getCollaborators(owner, repoName) getCollaborators(owner, repoName)

View File

@@ -87,7 +87,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
repository.name, repository.name,
form.description, form.description,
repository.repository.parentUserName.map { _ => repository.repository.parentUserName.map { _ =>
repository.repository.isPrivate repository.repository.`private`
} getOrElse form.isPrivate } getOrElse form.isPrivate
) )
// Change repository name // Change repository name
@@ -148,7 +148,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
get("/:owner/:repository/settings/collaborators")(ownerOnly { repository => get("/:owner/:repository/settings/collaborators")(ownerOnly { repository =>
html.collaborators( html.collaborators(
getCollaborators(repository.owner, repository.name), getCollaborators(repository.owner, repository.name),
getAccountByUserName(repository.owner).get.isGroupAccount, getAccountByUserName(repository.owner).get.groupAccount,
repository) repository)
}) })
@@ -156,7 +156,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* Add the collaborator. * Add the collaborator.
*/ */
post("/:owner/:repository/settings/collaborators/add", collaboratorForm)(ownerOnly { (form, repository) => post("/:owner/:repository/settings/collaborators/add", collaboratorForm)(ownerOnly { (form, repository) =>
if(!getAccountByUserName(repository.owner).get.isGroupAccount){ if(!getAccountByUserName(repository.owner).get.groupAccount){
addCollaborator(repository.owner, repository.name, form.userName) addCollaborator(repository.owner, repository.name, form.userName)
} }
redirect(s"/${repository.owner}/${repository.name}/settings/collaborators") redirect(s"/${repository.owner}/${repository.name}/settings/collaborators")
@@ -166,7 +166,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
* Add the collaborator. * Add the collaborator.
*/ */
get("/:owner/:repository/settings/collaborators/remove")(ownerOnly { repository => get("/:owner/:repository/settings/collaborators/remove")(ownerOnly { repository =>
if(!getAccountByUserName(repository.owner).get.isGroupAccount){ if(!getAccountByUserName(repository.owner).get.groupAccount){
removeCollaborator(repository.owner, repository.name, params("name")) removeCollaborator(repository.owner, repository.name, params("name"))
} }
redirect(s"/${repository.owner}/${repository.name}/settings/collaborators") redirect(s"/${repository.owner}/${repository.name}/settings/collaborators")
@@ -364,7 +364,7 @@ trait RepositorySettingsControllerBase extends ControllerBase {
override def validate(name: String, value: String, messages: Messages): Option[String] = override def validate(name: String, value: String, messages: Messages): Option[String] =
getAccountByUserName(value) match { getAccountByUserName(value) match {
case None => Some("User does not exist.") case None => Some("User does not exist.")
case Some(x) if(x.isGroupAccount) case Some(x) if(x.groupAccount)
=> Some("User does not exist.") => Some("User does not exist.")
case Some(x) if(x.userName == params("owner") || getCollaborators(params("owner"), params("repository")).contains(x.userName)) case Some(x) if(x.userName == params("owner") || getCollaborators(params("owner"), params("repository")).contains(x.userName))
=> Some("User can access this repository already.") => Some("User can access this repository already.")

View File

@@ -157,7 +157,7 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
get("/admin/users")(adminOnly { get("/admin/users")(adminOnly {
val includeRemoved = params.get("includeRemoved").map(_.toBoolean).getOrElse(false) val includeRemoved = params.get("includeRemoved").map(_.toBoolean).getOrElse(false)
val users = getAllUsers(includeRemoved) val users = getAllUsers(includeRemoved)
val members = users.collect { case account if(account.isGroupAccount) => val members = users.collect { case account if(account.groupAccount) =>
account.userName -> getGroupMembers(account.userName).map(_.userName) account.userName -> getGroupMembers(account.userName).map(_.userName)
}.toMap }.toMap
@@ -199,9 +199,9 @@ trait SystemSettingsControllerBase extends AccountManagementControllerBase {
password = form.password.map(sha1).getOrElse(account.password), password = form.password.map(sha1).getOrElse(account.password),
fullName = form.fullName, fullName = form.fullName,
mailAddress = form.mailAddress, mailAddress = form.mailAddress,
isAdmin = form.isAdmin, administrator = form.isAdmin,
url = form.url, url = form.url,
isRemoved = form.isRemoved)) removed = form.isRemoved))
updateImage(userName, form.fileId, form.clearImage) updateImage(userName, form.fileId, form.clearImage)
redirect("/admin/users") redirect("/admin/users")

View File

@@ -11,7 +11,7 @@ trait AccountComponent { self: Profile =>
val fullName = column[String]("FULL_NAME") val fullName = column[String]("FULL_NAME")
val mailAddress = column[String]("MAIL_ADDRESS") val mailAddress = column[String]("MAIL_ADDRESS")
val password = column[String]("PASSWORD") val password = column[String]("PASSWORD")
val isAdmin = column[Boolean]("ADMINISTRATOR") val administrator = column[Boolean]("ADMINISTRATOR")
val url = column[String]("URL") val url = column[String]("URL")
val registeredDate = column[java.util.Date]("REGISTERED_DATE") val registeredDate = column[java.util.Date]("REGISTERED_DATE")
val updatedDate = column[java.util.Date]("UPDATED_DATE") val updatedDate = column[java.util.Date]("UPDATED_DATE")
@@ -19,7 +19,7 @@ trait AccountComponent { self: Profile =>
val image = column[String]("IMAGE") val image = column[String]("IMAGE")
val groupAccount = column[Boolean]("GROUP_ACCOUNT") val groupAccount = column[Boolean]("GROUP_ACCOUNT")
val removed = column[Boolean]("REMOVED") val removed = column[Boolean]("REMOVED")
def * = (userName, fullName, mailAddress, password, isAdmin, url.?, registeredDate, updatedDate, lastLoginDate.?, image.?, groupAccount, removed) <> (Account.tupled, Account.unapply) def * = (userName, fullName, mailAddress, password, administrator, url.?, registeredDate, updatedDate, lastLoginDate.?, image.?, groupAccount, removed) <> (Account.tupled, Account.unapply)
} }
} }
@@ -28,12 +28,12 @@ case class Account(
fullName: String, fullName: String,
mailAddress: String, mailAddress: String,
password: String, password: String,
isAdmin: Boolean, administrator: Boolean,
url: Option[String], url: Option[String],
registeredDate: java.util.Date, registeredDate: java.util.Date,
updatedDate: java.util.Date, updatedDate: java.util.Date,
lastLoginDate: Option[java.util.Date], lastLoginDate: Option[java.util.Date],
image: Option[String], image: Option[String],
isGroupAccount: Boolean, groupAccount: Boolean,
isRemoved: Boolean removed: Boolean
) )

View File

@@ -8,13 +8,13 @@ trait GroupMemberComponent { self: Profile =>
class GroupMembers(tag: Tag) extends Table[GroupMember](tag, "GROUP_MEMBER") { class GroupMembers(tag: Tag) extends Table[GroupMember](tag, "GROUP_MEMBER") {
val groupName = column[String]("GROUP_NAME", O PrimaryKey) val groupName = column[String]("GROUP_NAME", O PrimaryKey)
val userName = column[String]("USER_NAME", O PrimaryKey) val userName = column[String]("USER_NAME", O PrimaryKey)
val isManager = column[Boolean]("MANAGER") val manager = column[Boolean]("MANAGER")
def * = (groupName, userName, isManager) <> (GroupMember.tupled, GroupMember.unapply) def * = (groupName, userName, manager) <> (GroupMember.tupled, GroupMember.unapply)
} }
} }
case class GroupMember( case class GroupMember(
groupName: String, groupName: String,
userName: String, userName: String,
isManager: Boolean manager: Boolean
) )

View File

@@ -26,7 +26,7 @@ trait RepositoryComponent extends TemplateComponent { self: Profile =>
case class Repository( case class Repository(
userName: String, userName: String,
repositoryName: String, repositoryName: String,
isPrivate: Boolean, `private`: Boolean,
description: Option[String], description: Option[String],
defaultBranch: String, defaultBranch: String,
registeredDate: java.util.Date, registeredDate: java.util.Date,

View File

@@ -5,6 +5,8 @@ import profile.simple._
import gitbucket.core.model.{Account, AccessToken} import gitbucket.core.model.{Account, AccessToken}
import gitbucket.core.util.StringUtil import gitbucket.core.util.StringUtil
import gitbucket.core.servlet.Database._
import io.getquill._
import scala.util.Random import scala.util.Random
@@ -28,27 +30,35 @@ trait AccessTokenService {
do{ do{
token = makeAccessTokenString token = makeAccessTokenString
hash = tokenToHash(token) hash = tokenToHash(token)
}while(AccessTokens.filter(_.tokenHash === hash.bind).exists.run) } while (
db.run(quote { (hash: String) => query[AccessToken].filter(_.tokenHash == hash).nonEmpty })(hash).head
)
val newToken = AccessToken( val newToken = AccessToken(
userName = userName, userName = userName,
note = note, note = note,
tokenHash = hash) tokenHash = hash)
// TODO Remain Slick code
val tokenId = (AccessTokens returning AccessTokens.map(_.accessTokenId)) += newToken val tokenId = (AccessTokens returning AccessTokens.map(_.accessTokenId)) += newToken
(tokenId, token) (tokenId, token)
} }
def getAccountByAccessToken(token: String)(implicit s: Session): Option[Account] = def getAccountByAccessToken(token: String): Option[Account] =
Accounts db.run(quote { (tokenHash: String) =>
.innerJoin(AccessTokens) query[AccessToken].filter(_.tokenHash == tokenHash)
.filter{ case (ac, t) => (ac.userName === t.userName) && (t.tokenHash === tokenToHash(token).bind) && (ac.removed === false.bind) } .join(query[Account]).on { (t, a) => t.userName == a.userName && a.registeredDate == false }
.map{ case (ac, t) => ac } .map { case (t, a) => a }
.firstOption })(tokenToHash(token)).headOption
def getAccessTokens(userName: String)(implicit s: Session): List[AccessToken] = def getAccessTokens(userName: String): List[AccessToken] =
AccessTokens.filter(_.userName === userName.bind).sortBy(_.accessTokenId.desc).list db.run(quote { (userName: String) =>
query[AccessToken].filter(_.userName == userName).sortBy(_.accessTokenId)(Ord.desc)
})(userName)
def deleteAccessToken(userName: String, accessTokenId: Int)(implicit s: Session): Unit = def deleteAccessToken(userName: String, accessTokenId: Int): Unit =
AccessTokens filter (t => t.userName === userName.bind && t.accessTokenId === accessTokenId) delete db.run(quote { (userName: String, accessTokenId: Int) =>
query[AccessToken].filter { t => t.userName == userName && t.accessTokenId == accessTokenId }.delete
})(List((userName, accessTokenId)))
} }

View File

@@ -1,20 +1,23 @@
package gitbucket.core.service package gitbucket.core.service
import gitbucket.core.model.{GroupMember, Account} import java.util.Date
import gitbucket.core.model.{GroupMember, Account, Collaborator, Repository}
import gitbucket.core.model.Profile._ import gitbucket.core.model.Profile._
import gitbucket.core.util.{StringUtil, LDAPUtil} import gitbucket.core.util.{StringUtil, LDAPUtil}
import gitbucket.core.service.SystemSettingsService.SystemSettings import gitbucket.core.service.SystemSettingsService.SystemSettings
import profile.simple._ import profile.simple._
import StringUtil._ import StringUtil._
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
// TODO Why is direct import required?
import gitbucket.core.model.Profile.dateColumnType import gitbucket.core.servlet.Database._
import io.getquill._
trait AccountService { trait AccountService {
private val logger = LoggerFactory.getLogger(classOf[AccountService]) private val logger = LoggerFactory.getLogger(classOf[AccountService])
def authenticate(settings: SystemSettings, userName: String, password: String)(implicit s: Session): Option[Account] = def authenticate(settings: SystemSettings, userName: String, password: String): Option[Account] =
if(settings.ldapAuthentication){ if(settings.ldapAuthentication){
ldapAuthentication(settings, userName, password) ldapAuthentication(settings, userName, password)
} else { } else {
@@ -24,22 +27,21 @@ trait AccountService {
/** /**
* Authenticate by internal database. * Authenticate by internal database.
*/ */
private def defaultAuthentication(userName: String, password: String)(implicit s: Session) = { private def defaultAuthentication(userName: String, password: String) = {
getAccountByUserName(userName).collect { getAccountByUserName(userName).collect {
case account if(!account.isGroupAccount && account.password == sha1(password)) => Some(account) case account if(!account.groupAccount && account.password == sha1(password)) => Some(account)
} getOrElse None } getOrElse None
} }
/** /**
* Authenticate by LDAP. * Authenticate by LDAP.
*/ */
private def ldapAuthentication(settings: SystemSettings, userName: String, password: String) private def ldapAuthentication(settings: SystemSettings, userName: String, password: String): Option[Account] = {
(implicit s: Session): Option[Account] = {
LDAPUtil.authenticate(settings.ldap.get, userName, password) match { LDAPUtil.authenticate(settings.ldap.get, userName, password) match {
case Right(ldapUserInfo) => { case Right(ldapUserInfo) => {
// Create or update account by LDAP information // Create or update account by LDAP information
getAccountByUserName(ldapUserInfo.userName, true) match { getAccountByUserName(ldapUserInfo.userName, true) match {
case Some(x) if(!x.isRemoved) => { case Some(x) if(!x.removed) => {
if(settings.ldap.get.mailAttribute.getOrElse("").isEmpty) { if(settings.ldap.get.mailAttribute.getOrElse("").isEmpty) {
updateAccount(x.copy(fullName = ldapUserInfo.fullName)) updateAccount(x.copy(fullName = ldapUserInfo.fullName))
} else { } else {
@@ -47,16 +49,16 @@ trait AccountService {
} }
getAccountByUserName(ldapUserInfo.userName) getAccountByUserName(ldapUserInfo.userName)
} }
case Some(x) if(x.isRemoved) => { case Some(x) if(x.removed) => {
logger.info("LDAP Authentication Failed: Account is already registered but disabled.") logger.info("LDAP Authentication Failed: Account is already registered but disabled.")
defaultAuthentication(userName, password) defaultAuthentication(userName, password)
} }
case None => getAccountByMailAddress(ldapUserInfo.mailAddress, true) match { case None => getAccountByMailAddress(ldapUserInfo.mailAddress, true) match {
case Some(x) if(!x.isRemoved) => { case Some(x) if(!x.removed) => {
updateAccount(x.copy(fullName = ldapUserInfo.fullName)) updateAccount(x.copy(fullName = ldapUserInfo.fullName))
getAccountByUserName(ldapUserInfo.userName) getAccountByUserName(ldapUserInfo.userName)
} }
case Some(x) if(x.isRemoved) => { case Some(x) if(x.removed) => {
logger.info("LDAP Authentication Failed: Account is already registered but disabled.") logger.info("LDAP Authentication Failed: Account is already registered but disabled.")
defaultAuthentication(userName, password) defaultAuthentication(userName, password)
} }
@@ -74,113 +76,163 @@ trait AccountService {
} }
} }
def getAccountByUserName(userName: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = def getAccountByUserName(userName: String, includeRemoved: Boolean = false): Option[Account] = {
Accounts filter(t => (t.userName === userName.bind) && (t.removed === false.bind, !includeRemoved)) firstOption db.run(quote { (userName: String, includeRemoved: Boolean) =>
query[Account].filter { t =>
if(includeRemoved){
t.userName == userName
} else {
t.userName == userName && t.removed == false
}
}
})(userName, includeRemoved).headOption
}
def getAccountsByUserNames(userNames: Set[String], knowns:Set[Account], includeRemoved: Boolean = false)(implicit s: Session): Map[String, Account] = {
def getAccountsByUserNames(userNames: Set[String], knowns:Set[Account], includeRemoved: Boolean = false): Map[String, Account] = {
val map = knowns.map(a => a.userName -> a).toMap val map = knowns.map(a => a.userName -> a).toMap
val needs = userNames -- map.keySet val needs = userNames -- map.keySet
if(needs.isEmpty){ if(needs.isEmpty){
map map
} else { } else {
map ++ Accounts.filter(t => (t.userName inSetBind needs) && (t.removed === false.bind, !includeRemoved)).list.map(a => a.userName -> a).toMap map ++ db.run(quote { (userNames: Set[String]) =>
query[Account].filter { t => userNames.contains(t.userName) && t.removed == false }
})(userNames.toSet).map { a => a.userName -> a }.toMap
} }
} }
def getAccountByMailAddress(mailAddress: String, includeRemoved: Boolean = false)(implicit s: Session): Option[Account] = def getAccountByMailAddress(mailAddress: String, includeRemoved: Boolean = false): Option[Account] = {
Accounts filter(t => (t.mailAddress.toLowerCase === mailAddress.toLowerCase.bind) && (t.removed === false.bind, !includeRemoved)) firstOption db.run(quote { (mailAddress: String, includeRemoved: Boolean) =>
query[Account].filter { t =>
def getAllUsers(includeRemoved: Boolean = true)(implicit s: Session): List[Account] =
if(includeRemoved){ if(includeRemoved){
Accounts sortBy(_.userName) list t.mailAddress.toLowerCase == mailAddress.toLowerCase
} else { } else {
Accounts filter (_.removed === false.bind) sortBy(_.userName) list t.mailAddress.toLowerCase == mailAddress.toLowerCase && t.removed == false
}
}
})(mailAddress, includeRemoved).headOption
} }
def createAccount(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, url: Option[String]) def getAllUsers(includeRemoved: Boolean = true): List[Account] = {
(implicit s: Session): Unit = db.run(
Accounts insert Account( if(includeRemoved){
quote { query[Account].sortBy(_.userName) }
} else {
quote { query[Account].filter(_.removed == false).sortBy(_.userName) }
}
)
}
def createAccount(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, url: Option[String]): Unit = {
db.run(quote { query[Account].insert })(Account(
userName = userName, userName = userName,
password = password, password = password,
fullName = fullName, fullName = fullName,
mailAddress = mailAddress, mailAddress = mailAddress,
isAdmin = isAdmin, administrator = isAdmin,
url = url, url = url,
registeredDate = currentDate, registeredDate = currentDate,
updatedDate = currentDate, updatedDate = currentDate,
lastLoginDate = None, lastLoginDate = None,
image = None, image = None,
isGroupAccount = false, groupAccount = false,
isRemoved = false) removed = false
))
}
def updateAccount(account: Account)(implicit s: Session): Unit = def updateAccount(account: Account): Unit = {
Accounts db.run(quote { (userName: String, password: String, fullName: String, mailAddress: String, administrator: Boolean,
.filter { a => a.userName === account.userName.bind } url: Option[String], registeredDate: Date, updatedDate: Date, lastLoginDate: Option[Date], removed: Boolean) =>
.map { a => (a.password, a.fullName, a.mailAddress, a.isAdmin, a.url.?, a.registeredDate, a.updatedDate, a.lastLoginDate.?, a.removed) } query[Account].filter(_.userName == userName).update(
.update ( _.password -> password,
_.fullName -> fullName,
_.mailAddress -> mailAddress,
_.administrator -> administrator,
_.url -> url,
_.registeredDate -> registeredDate,
_.updatedDate -> updatedDate,
_.lastLoginDate -> lastLoginDate,
_.removed -> removed
)
})((
account.userName,
account.password, account.password,
account.fullName, account.fullName,
account.mailAddress, account.mailAddress,
account.isAdmin, account.administrator,
account.url, account.url,
account.registeredDate, account.registeredDate,
currentDate, currentDate,
account.lastLoginDate, account.lastLoginDate,
account.isRemoved) account.removed
))
}
def updateAvatarImage(userName: String, image: Option[String])(implicit s: Session): Unit = def updateAvatarImage(userName: String, image: Option[String]): Unit = {
Accounts.filter(_.userName === userName.bind).map(_.image.?).update(image) db.run(quote { (userName: String, image: Option[String]) =>
query[Account].filter(_.userName == userName).update(_.image -> image)
})((userName, image))
}
def updateLastLoginDate(userName: String)(implicit s: Session): Unit = def updateLastLoginDate(userName: String): Unit = {
Accounts.filter(_.userName === userName.bind).map(_.lastLoginDate).update(currentDate) db.run(quote { (userName: String, lastLoginDate: Option[Date]) =>
query[Account].filter(_.userName == userName).update(_.lastLoginDate -> lastLoginDate)
})((userName, Some(currentDate)))
}
def createGroup(groupName: String, url: Option[String])(implicit s: Session): Unit = def createGroup(groupName: String, url: Option[String]): Unit = {
Accounts insert Account( db.run( quote { query[Account].insert })(List(Account(
userName = groupName, userName = groupName,
password = "", password = "",
fullName = groupName, fullName = groupName,
mailAddress = groupName + "@devnull", mailAddress = groupName + "@devnull",
isAdmin = false, administrator = false,
url = url, url = url,
registeredDate = currentDate, registeredDate = currentDate,
updatedDate = currentDate, updatedDate = currentDate,
lastLoginDate = None, lastLoginDate = None,
image = None, image = None,
isGroupAccount = true, groupAccount = true,
isRemoved = false) removed = false
)))
}
def updateGroup(groupName: String, url: Option[String], removed: Boolean)(implicit s: Session): Unit = def updateGroup(groupName: String, url: Option[String], removed: Boolean): Unit = {
Accounts.filter(_.userName === groupName.bind).map(t => t.url.? -> t.removed).update(url, removed) db.run(quote { (groupName: String, url: Option[String], removed: Boolean) =>
query[Account].filter(_.userName == groupName).update(_.url -> url, _.removed -> removed)
})(List((groupName, url, removed)))
}
def updateGroupMembers(groupName: String, members: List[(String, Boolean)]): Unit = {
db.run(quote { (groupName: String) => query[GroupMember].filter(_.groupName == groupName).delete })(groupName)
def updateGroupMembers(groupName: String, members: List[(String, Boolean)])(implicit s: Session): Unit = {
GroupMembers.filter(_.groupName === groupName.bind).delete
members.foreach { case (userName, isManager) => members.foreach { case (userName, isManager) =>
GroupMembers insert GroupMember (groupName, userName, isManager) db.run(quote { query[GroupMember].insert })(GroupMember(groupName, userName, isManager))
} }
} }
def getGroupMembers(groupName: String)(implicit s: Session): List[GroupMember] = def getGroupMembers(groupName: String): List[GroupMember] = {
GroupMembers db.run(quote { (groupName: String) =>
.filter(_.groupName === groupName.bind) query[GroupMember].filter(_.groupName == groupName).sortBy(_.userName)
.sortBy(_.userName) })(groupName)
.list
def getGroupsByUserName(userName: String)(implicit s: Session): List[String] =
GroupMembers
.filter(_.userName === userName.bind)
.sortBy(_.groupName)
.map(_.groupName)
.list
def removeUserRelatedData(userName: String)(implicit s: Session): Unit = {
GroupMembers.filter(_.userName === userName.bind).delete
Collaborators.filter(_.collaboratorName === userName.bind).delete
Repositories.filter(_.userName === userName.bind).delete
} }
def getGroupNames(userName: String)(implicit s: Session): List[String] = { def getGroupsByUserName(userName: String): List[String] = {
List(userName) ++ db.run(quote { (userName: String) =>
Collaborators.filter(_.collaboratorName === userName.bind).sortBy(_.userName).map(_.userName).list query[GroupMember].filter(_.userName == userName).sortBy(_.groupName).map(_.groupName)
})(userName)
}
def removeUserRelatedData(userName: String): Unit = {
db.run(quote { (userName: String) => query[GroupMember].filter(_.userName == userName).delete })(userName)
db.run(quote { (userName: String) => query[Collaborator].filter(_.collaboratorName == userName).delete })(userName)
db.run(quote { (userName: String) => query[Repository].filter(_.userName == userName).delete })(userName)
}
def getGroupNames(userName: String): List[String] = {
List(userName) ++ db.run(quote { (userName: String) =>
query[Collaborator].filter(_.collaboratorName == userName).sortBy(_.userName).map(_.userName)
})(userName)
} }
} }

View File

@@ -1,194 +1,180 @@
package gitbucket.core.service package gitbucket.core.service
import gitbucket.core.model.Activity import gitbucket.core.model._
import gitbucket.core.model.Profile._ import gitbucket.core.model.Profile._
import gitbucket.core.util.JGitUtil import gitbucket.core.util.JGitUtil
import profile.simple._ import profile.simple._
import gitbucket.core.servlet.Database._
import io.getquill._
trait ActivityService { trait ActivityService {
def deleteOldActivities(limit: Int)(implicit s: Session): Int = { def deleteOldActivities(limit: Int): Int =
Activities.map(_.activityId).sortBy(_ desc).drop(limit).firstOption.map { id => db.run (quote { (limit: Int) =>
Activities.filter(_.activityId <= id.bind).delete query[Activity].map(_.activityId).sortBy(x => x)(Ord.desc).drop(limit)
})(limit).headOption.map { activityId =>
db.run (
quote { (activityId: Int) => query[Activity].filter(_.activityId <= activityId).delete }
)(activityId)
} getOrElse 0 } getOrElse 0
}
def getActivitiesByUser(activityUserName: String, isPublic: Boolean)(implicit s: Session): List[Activity] = def getActivitiesByUser(activityUserName: String, isPublic: Boolean): List[Activity] =
Activities db.run(quote { (activityUserName: String, isPublic: Boolean) =>
.innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) query[Activity].join(query[Repository]).on((a, r) => a.userName == r.userName && a.repositoryName == r.repositoryName)
.filter { case (t1, t2) => .filter { case (a, r) =>
if(isPublic){ if(isPublic){
(t1.activityUserName === activityUserName.bind) && (t2.isPrivate === false.bind) a.activityUserName == activityUserName
} else { } else {
(t1.activityUserName === activityUserName.bind) a.activityUserName == activityUserName && r.`private` == false
} }
} }
.sortBy { case (t1, t2) => t1.activityId desc } .sortBy { case (a, r) => a.activityId }(Ord.desc)
.map { case (t1, t2) => t1 } .map { case (a, r) => a }
.take(30) .take(30)
.list })(activityUserName, isPublic)
def getRecentActivities()(implicit s: Session): List[Activity] = def getRecentActivities(): List[Activity] =
Activities db.run(quote {
.innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) query[Activity].join(query[Repository]).on((a, r) => a.userName == r.userName && a.repositoryName == r.repositoryName)
.filter { case (t1, t2) => t2.isPrivate === false.bind } .filter { case (a, r) => r.`private` == false}
.sortBy { case (t1, t2) => t1.activityId desc } .sortBy { case (a, r) => a.activityId }(Ord.desc)
.map { case (t1, t2) => t1 } .map { case (a, r) => a }
.take(30) .take(30)
.list })
def getRecentActivitiesByOwners(owners : Set[String])(implicit s: Session): List[Activity] = def getRecentActivitiesByOwners(owners : Set[String]): List[Activity] =
Activities db.run(quote { (owners: Set[String]) =>
.innerJoin(Repositories).on((t1, t2) => t1.byRepository(t2.userName, t2.repositoryName)) query[Activity].join(query[Repository]).on((a, r) => a.userName == r.userName && a.repositoryName == r.repositoryName)
.filter { case (t1, t2) => (t2.isPrivate === false.bind) || (t2.userName inSetBind owners) } .filter { case (a, r) => r.`private` == false || owners.contains(r.userName) }
.sortBy { case (t1, t2) => t1.activityId desc } .sortBy { case (a, r) => a.activityId }(Ord.desc)
.map { case (t1, t2) => t1 } .map { case (a, r) => a }
.take(30) .take(30)
.list })(owners)
def recordCreateRepositoryActivity(userName: String, repositoryName: String, activityUserName: String) def recordCreateRepositoryActivity(userName: String, repositoryName: String, activityUserName: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"create_repository", "create_repository",
s"[user:${activityUserName}] created [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] created [repo:${userName}/${repositoryName}]",
None, None)
currentDate)
def recordCreateIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String) def recordCreateIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"open_issue", "open_issue",
s"[user:${activityUserName}] opened issue [issue:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] opened issue [issue:${userName}/${repositoryName}#${issueId}]",
Some(title), Some(title))
currentDate)
def recordCloseIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String) def recordCloseIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"close_issue", "close_issue",
s"[user:${activityUserName}] closed issue [issue:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] closed issue [issue:${userName}/${repositoryName}#${issueId}]",
Some(title), Some(title))
currentDate)
def recordClosePullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String) def recordClosePullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"close_issue", "close_issue",
s"[user:${activityUserName}] closed pull request [pullreq:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] closed pull request [pullreq:${userName}/${repositoryName}#${issueId}]",
Some(title), Some(title))
currentDate)
def recordReopenIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String) def recordReopenIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"reopen_issue", "reopen_issue",
s"[user:${activityUserName}] reopened issue [issue:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] reopened issue [issue:${userName}/${repositoryName}#${issueId}]",
Some(title), Some(title))
currentDate)
def recordCommentIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, comment: String) def recordCommentIssueActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, comment: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"comment_issue", "comment_issue",
s"[user:${activityUserName}] commented on issue [issue:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] commented on issue [issue:${userName}/${repositoryName}#${issueId}]",
Some(cut(comment, 200)), Some(cut(comment, 200)))
currentDate)
def recordCommentPullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, comment: String) def recordCommentPullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, comment: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"comment_issue", "comment_issue",
s"[user:${activityUserName}] commented on pull request [pullreq:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] commented on pull request [pullreq:${userName}/${repositoryName}#${issueId}]",
Some(cut(comment, 200)), Some(cut(comment, 200)))
currentDate)
def recordCommentCommitActivity(userName: String, repositoryName: String, activityUserName: String, commitId: String, comment: String) def recordCommentCommitActivity(userName: String, repositoryName: String, activityUserName: String, commitId: String, comment: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"comment_commit", "comment_commit",
s"[user:${activityUserName}] commented on commit [commit:${userName}/${repositoryName}@${commitId}]", s"[user:${activityUserName}] commented on commit [commit:${userName}/${repositoryName}@${commitId}]",
Some(cut(comment, 200)), Some(cut(comment, 200)))
currentDate
)
def recordCreateWikiPageActivity(userName: String, repositoryName: String, activityUserName: String, pageName: String) def recordCreateWikiPageActivity(userName: String, repositoryName: String, activityUserName: String, pageName: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"create_wiki", "create_wiki",
s"[user:${activityUserName}] created the [repo:${userName}/${repositoryName}] wiki", s"[user:${activityUserName}] created the [repo:${userName}/${repositoryName}] wiki",
Some(pageName), Some(pageName))
currentDate)
def recordEditWikiPageActivity(userName: String, repositoryName: String, activityUserName: String, pageName: String, commitId: String) def recordEditWikiPageActivity(userName: String, repositoryName: String, activityUserName: String, pageName: String, commitId: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"edit_wiki", "edit_wiki",
s"[user:${activityUserName}] edited the [repo:${userName}/${repositoryName}] wiki", s"[user:${activityUserName}] edited the [repo:${userName}/${repositoryName}] wiki",
Some(pageName + ":" + commitId), Some(pageName + ":" + commitId))
currentDate)
def recordPushActivity(userName: String, repositoryName: String, activityUserName: String, def recordPushActivity(userName: String, repositoryName: String, activityUserName: String,
branchName: String, commits: List[JGitUtil.CommitInfo])(implicit s: Session): Unit = branchName: String, commits: List[JGitUtil.CommitInfo]): Unit =
Activities insert Activity(userName, repositoryName, activityUserName, insertActivity(userName, repositoryName, activityUserName,
"push", "push",
s"[user:${activityUserName}] pushed to [branch:${userName}/${repositoryName}#${branchName}] at [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] pushed to [branch:${userName}/${repositoryName}#${branchName}] at [repo:${userName}/${repositoryName}]",
Some(commits.map { commit => commit.id + ":" + commit.shortMessage }.mkString("\n")), Some(commits.map { commit => commit.id + ":" + commit.shortMessage }.mkString("\n")))
currentDate)
def recordCreateTagActivity(userName: String, repositoryName: String, activityUserName: String, def recordCreateTagActivity(userName: String, repositoryName: String, activityUserName: String,
tagName: String, commits: List[JGitUtil.CommitInfo])(implicit s: Session): Unit = tagName: String, commits: List[JGitUtil.CommitInfo]): Unit =
Activities insert Activity(userName, repositoryName, activityUserName, insertActivity(userName, repositoryName, activityUserName,
"create_tag", "create_tag",
s"[user:${activityUserName}] created tag [tag:${userName}/${repositoryName}#${tagName}] at [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] created tag [tag:${userName}/${repositoryName}#${tagName}] at [repo:${userName}/${repositoryName}]",
None, None)
currentDate)
def recordDeleteTagActivity(userName: String, repositoryName: String, activityUserName: String, def recordDeleteTagActivity(userName: String, repositoryName: String, activityUserName: String,
tagName: String, commits: List[JGitUtil.CommitInfo])(implicit s: Session): Unit = tagName: String, commits: List[JGitUtil.CommitInfo]): Unit =
Activities insert Activity(userName, repositoryName, activityUserName, insertActivity(userName, repositoryName, activityUserName,
"delete_tag", "delete_tag",
s"[user:${activityUserName}] deleted tag ${tagName} at [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] deleted tag ${tagName} at [repo:${userName}/${repositoryName}]",
None, None)
currentDate)
def recordCreateBranchActivity(userName: String, repositoryName: String, activityUserName: String, branchName: String) def recordCreateBranchActivity(userName: String, repositoryName: String, activityUserName: String, branchName: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"create_branch", "create_branch",
s"[user:${activityUserName}] created branch [branch:${userName}/${repositoryName}#${branchName}] at [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] created branch [branch:${userName}/${repositoryName}#${branchName}] at [repo:${userName}/${repositoryName}]",
None, None)
currentDate)
def recordDeleteBranchActivity(userName: String, repositoryName: String, activityUserName: String, branchName: String) def recordDeleteBranchActivity(userName: String, repositoryName: String, activityUserName: String, branchName: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"delete_branch", "delete_branch",
s"[user:${activityUserName}] deleted branch ${branchName} at [repo:${userName}/${repositoryName}]", s"[user:${activityUserName}] deleted branch ${branchName} at [repo:${userName}/${repositoryName}]",
None, None)
currentDate)
def recordForkActivity(userName: String, repositoryName: String, activityUserName: String, forkedUserName: String)(implicit s: Session): Unit = def recordForkActivity(userName: String, repositoryName: String, activityUserName: String, forkedUserName: String): Unit =
Activities insert Activity(userName, repositoryName, activityUserName, insertActivity(userName, repositoryName, activityUserName,
"fork", "fork",
s"[user:${activityUserName}] forked [repo:${userName}/${repositoryName}] to [repo:${forkedUserName}/${repositoryName}]", s"[user:${activityUserName}] forked [repo:${userName}/${repositoryName}] to [repo:${forkedUserName}/${repositoryName}]",
None, None)
currentDate)
def recordPullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String) def recordPullRequestActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, title: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"open_pullreq", "open_pullreq",
s"[user:${activityUserName}] opened pull request [pullreq:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] opened pull request [pullreq:${userName}/${repositoryName}#${issueId}]",
Some(title), Some(title))
currentDate)
def recordMergeActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, message: String) def recordMergeActivity(userName: String, repositoryName: String, activityUserName: String, issueId: Int, message: String): Unit =
(implicit s: Session): Unit = insertActivity(userName, repositoryName, activityUserName,
Activities insert Activity(userName, repositoryName, activityUserName,
"merge_pullreq", "merge_pullreq",
s"[user:${activityUserName}] merged pull request [pullreq:${userName}/${repositoryName}#${issueId}]", s"[user:${activityUserName}] merged pull request [pullreq:${userName}/${repositoryName}#${issueId}]",
Some(message), Some(message))
currentDate)
private def insertActivity(userName: String, repositoryName: String, activityUserName: String, activityType: String,
message: String, additionalInfo: Option[String]): Unit = {
db.run(quote { query[Activity].insert })(Activity(
userName = userName,
repositoryName = repositoryName,
activityUserName = activityUserName,
activityType = activityType,
message = message,
additionalInfo = additionalInfo,
activityDate = currentDate
))
}
private def cut(value: String, length: Int): String = private def cut(value: String, length: Int): String =
if(value.length > length) value.substring(0, length) + "..." else value if(value.length > length) value.substring(0, length) + "..." else value

View File

@@ -1,35 +1,34 @@
package gitbucket.core.service package gitbucket.core.service
import gitbucket.core.model.CommitComment import gitbucket.core.model.CommitComment
import gitbucket.core.util.{StringUtil, Implicits}
import scala.slick.jdbc.{StaticQuery => Q}
import Q.interpolation
import gitbucket.core.model.Profile._ import gitbucket.core.model.Profile._
import profile.simple._ import profile.simple._
import Implicits._
import StringUtil._ import gitbucket.core.servlet.Database._
import io.getquill._
trait CommitsService { trait CommitsService {
def getCommitComments(owner: String, repository: String, commitId: String, includePullRequest: Boolean)(implicit s: Session) = def getCommitComments(owner: String, repository: String, commitId: String, includePullRequest: Boolean) =
CommitComments filter { db.run(quote { (owner: String, repository: String, commitId: String, includePullRequest: Boolean) =>
t => t.byCommit(owner, repository, commitId) && (t.issueId.isEmpty || includePullRequest) query[CommitComment].filter { t =>
} list t.userName == owner && t.repositoryName == repository && t.commitId == commitId && (t.issueId.isEmpty || includePullRequest)
}
})(owner, repository, commitId, includePullRequest)
def getCommitComment(owner: String, repository: String, commentId: String)(implicit s: Session) = def getCommitComment(owner: String, repository: String, commentId: String) =
if (commentId forall (_.isDigit)) if (commentId forall (_.isDigit))
CommitComments filter { t => db.run(quote { (owner: String, repository: String, commentId: Int) =>
t.byPrimaryKey(commentId.toInt) && t.byRepository(owner, repository) query[CommitComment].filter(t => t.userName == owner && t.repositoryName == repository && t.commentId == commentId)
} firstOption })(owner, repository, commentId.toInt).headOption
else else
None None
def createCommitComment(owner: String, repository: String, commitId: String, loginUser: String, def createCommitComment(owner: String, repository: String, commitId: String, loginUser: String,
content: String, fileName: Option[String], oldLine: Option[Int], newLine: Option[Int], content: String, fileName: Option[String], oldLine: Option[Int], newLine: Option[Int],
issueId: Option[Int])(implicit s: Session): Int = issueId: Option[Int])(implicit s: Session): Int =
CommitComments.autoInc insert CommitComment( CommitComments.autoInc insert CommitComment( // TODO Remain Slick code
userName = owner, userName = owner,
repositoryName = repository, repositoryName = repository,
commitId = commitId, commitId = commitId,
@@ -42,13 +41,12 @@ trait CommitsService {
updatedDate = currentDate, updatedDate = currentDate,
issueId = issueId) issueId = issueId)
def updateCommitComment(commentId: Int, content: String)(implicit s: Session) = def updateCommitComment(commentId: Int, content: String) =
CommitComments db.run(quote { (commentId: Int, content: String, updatedDate: java.util.Date) =>
.filter (_.byPrimaryKey(commentId)) query[CommitComment].filter(_.commentId == commentId).update(_.content -> content, _.updatedDate -> updatedDate)
.map { t => })(commentId, content, currentDate)
t.content -> t.updatedDate
}.update (content, currentDate) def deleteCommitComment(commentId: Int) =
db.run(quote { (commentId: Int) => query[CommitComment].filter(_.commentId == commentId).delete })(commentId)
def deleteCommitComment(commentId: Int)(implicit s: Session) =
CommitComments filter (_.byPrimaryKey(commentId)) delete
} }

View File

@@ -76,7 +76,7 @@ object ProtectedBranchService {
includeAdministrators: Boolean) extends AccountService with CommitStatusService { includeAdministrators: Boolean) extends AccountService with CommitStatusService {
def isAdministrator(pusher: String)(implicit session: Session): Boolean = def isAdministrator(pusher: String)(implicit session: Session): Boolean =
pusher == owner || getGroupMembers(owner).filter(gm => gm.userName == pusher && gm.isManager).nonEmpty pusher == owner || getGroupMembers(owner).filter(gm => gm.userName == pusher && gm.manager).nonEmpty
/** /**
* Can't be force pushed * Can't be force pushed

View File

@@ -22,7 +22,7 @@ trait RepositoryCreationService {
insertRepository(name, owner, description, isPrivate) insertRepository(name, owner, description, isPrivate)
// Add collaborators for group repository // Add collaborators for group repository
if(ownerAccount.isGroupAccount){ if(ownerAccount.groupAccount){
getGroupMembers(owner).foreach { member => getGroupMembers(owner).foreach { member =>
addCollaborator(owner, name, member.userName) addCollaborator(owner, name, member.userName)
} }

View File

@@ -27,7 +27,7 @@ trait RepositoryService { self: AccountService =>
Repository( Repository(
userName = userName, userName = userName,
repositoryName = repositoryName, repositoryName = repositoryName,
isPrivate = isPrivate, `private` = isPrivate,
description = description, description = description,
defaultBranch = "master", defaultBranch = "master",
registeredDate = currentDate, registeredDate = currentDate,
@@ -115,7 +115,7 @@ trait RepositoryService { self: AccountService =>
repositoryName = newRepositoryName repositoryName = newRepositoryName
)) :_*) )) :_*)
if(account.isGroupAccount){ if(account.groupAccount){
Collaborators.insertAll(getGroupMembers(newUserName).map(m => Collaborator(newUserName, newRepositoryName, m.userName)) :_*) Collaborators.insertAll(getGroupMembers(newUserName).map(m => Collaborator(newUserName, newRepositoryName, m.userName)) :_*)
} else { } else {
Collaborators.insertAll(collaborators.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)) :_*) Collaborators.insertAll(collaborators.map(_.copy(userName = newUserName, repositoryName = newRepositoryName)) :_*)
@@ -270,9 +270,9 @@ trait RepositoryService { self: AccountService =>
(implicit s: Session): List[RepositoryInfo] = { (implicit s: Session): List[RepositoryInfo] = {
(loginAccount match { (loginAccount match {
// for Administrators // for Administrators
case Some(x) if(x.isAdmin) => Repositories case Some(x) if(x.administrator) => Repositories
// for Normal Users // for Normal Users
case Some(x) if(!x.isAdmin) => case Some(x) if(!x.administrator) =>
Repositories filter { t => (t.isPrivate === false.bind) || (t.userName === x.userName) || Repositories filter { t => (t.isPrivate === false.bind) || (t.userName === x.userName) ||
(Collaborators.filter { t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName === x.userName.bind)} exists) (Collaborators.filter { t2 => t2.byRepository(t.userName, t.repositoryName) && (t2.collaboratorName === x.userName.bind)} exists)
} }
@@ -297,8 +297,8 @@ trait RepositoryService { self: AccountService =>
} }
private def getRepositoryManagers(userName: String)(implicit s: Session): Seq[String] = private def getRepositoryManagers(userName: String)(implicit s: Session): Seq[String] =
if(getAccountByUserName(userName).exists(_.isGroupAccount)){ if(getAccountByUserName(userName).exists(_.groupAccount)){
getGroupMembers(userName).collect { case x if(x.isManager) => x.userName } getGroupMembers(userName).collect { case x if(x.manager) => x.userName }
} else { } else {
Seq(userName) Seq(userName)
} }
@@ -365,7 +365,7 @@ trait RepositoryService { self: AccountService =>
def hasWritePermission(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = { def hasWritePermission(owner: String, repository: String, loginAccount: Option[Account])(implicit s: Session): Boolean = {
loginAccount match { loginAccount match {
case Some(a) if(a.isAdmin) => true case Some(a) if(a.administrator) => true
case Some(a) if(a.userName == owner) => true case Some(a) if(a.userName == owner) => true
case Some(a) if(getCollaborators(owner, repository).contains(a.userName)) => true case Some(a) if(getCollaborators(owner, repository).contains(a.userName)) => true
case _ => false case _ => false

View File

@@ -76,14 +76,14 @@ class BasicAuthenticationFilter extends Filter with RepositoryService with Accou
case Array(_, repositoryOwner, repositoryName, _*) => case Array(_, repositoryOwner, repositoryName, _*) =>
getRepository(repositoryOwner, repositoryName.replaceFirst("\\.wiki\\.git$|\\.git$", "")) match { getRepository(repositoryOwner, repositoryName.replaceFirst("\\.wiki\\.git$|\\.git$", "")) match {
case Some(repository) => { case Some(repository) => {
if(!isUpdating && !repository.repository.isPrivate && settings.allowAnonymousAccess){ if(!isUpdating && !repository.repository.`private` && settings.allowAnonymousAccess){
chain.doFilter(request, response) chain.doFilter(request, response)
} else { } else {
val passed = for { val passed = for {
auth <- Option(request.getHeader("Authorization")) auth <- Option(request.getHeader("Authorization"))
Array(username, password) = decodeAuthHeader(auth).split(":", 2) Array(username, password) = decodeAuthHeader(auth).split(":", 2)
account <- authenticate(settings, username, password) account <- authenticate(settings, username, password)
} yield if(isUpdating || repository.repository.isPrivate){ } yield if(isUpdating || repository.repository.`private`){
if(hasWritePermission(repository.owner, repository.name, Some(account))){ if(hasWritePermission(repository.owner, repository.name, Some(account))){
request.setAttribute(Keys.Request.UserName, account.userName) request.setAttribute(Keys.Request.UserName, account.userName)
true true

View File

@@ -4,10 +4,14 @@ import javax.servlet._
import javax.servlet.http.HttpServletRequest import javax.servlet.http.HttpServletRequest
import com.mchange.v2.c3p0.ComboPooledDataSource import com.mchange.v2.c3p0.ComboPooledDataSource
import gitbucket.core.util.DatabaseConfig import gitbucket.core.util.DatabaseConfig
import io.getquill._
import io.getquill.naming.SnakeCase
import io.getquill.sources.sql.idiom.H2Dialect
import org.scalatra.ScalatraBase import org.scalatra.ScalatraBase
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import slick.jdbc.JdbcBackend.{Database => SlickDatabase, Session} import slick.jdbc.JdbcBackend.{Database => SlickDatabase, Session}
import gitbucket.core.util.Keys import gitbucket.core.util.Keys
import Database._
/** /**
* Controls the transaction with the open session in view pattern. * Controls the transaction with the open session in view pattern.
@@ -25,6 +29,8 @@ class TransactionFilter extends Filter {
// assets don't need transaction // assets don't need transaction
chain.doFilter(req, res) chain.doFilter(req, res)
} else { } else {
db.transaction {
// TODO Delete after moving to quill
Database() withTransaction { session => Database() withTransaction { session =>
// Register Scalatra error callback to rollback transaction // Register Scalatra error callback to rollback transaction
ScalatraBase.onFailure { _ => ScalatraBase.onFailure { _ =>
@@ -39,6 +45,7 @@ class TransactionFilter extends Filter {
} }
} }
} }
}
} }
@@ -46,6 +53,9 @@ object Database {
private val logger = LoggerFactory.getLogger(Database.getClass) private val logger = LoggerFactory.getLogger(Database.getClass)
lazy val db = source(new JdbcSourceConfig[H2Dialect, SnakeCase]("db"))
// TODO Delete after moving to quill
private val dataSource: ComboPooledDataSource = { private val dataSource: ComboPooledDataSource = {
val ds = new ComboPooledDataSource val ds = new ComboPooledDataSource
ds.setDriverClass(DatabaseConfig.driver) ds.setDriverClass(DatabaseConfig.driver)
@@ -56,15 +66,19 @@ object Database {
ds ds
} }
private val db: SlickDatabase = { // TODO Delete after moving to quill
private val slickDatabase: SlickDatabase = {
SlickDatabase.forDataSource(dataSource) SlickDatabase.forDataSource(dataSource)
} }
def apply(): SlickDatabase = db // TODO Delete after moving to quill
def apply(): SlickDatabase = slickDatabase
// TODO Delete after moving to quill
def getSession(req: ServletRequest): Session = def getSession(req: ServletRequest): Session =
req.getAttribute(Keys.Request.DBSession).asInstanceOf[Session] req.getAttribute(Keys.Request.DBSession).asInstanceOf[Session]
// TODO Delete after moving to quill
def closeDataSource(): Unit = dataSource.close def closeDataSource(): Unit = dataSource.close
} }

View File

@@ -92,7 +92,7 @@ class DefaultGitUploadPack(owner: String, repoName: String) extends DefaultGitCo
override protected def runTask(user: String)(implicit session: Session): Unit = { override protected def runTask(user: String)(implicit session: Session): Unit = {
getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).foreach { repositoryInfo => getRepository(owner, repoName.replaceFirst("\\.wiki\\Z", "")).foreach { repositoryInfo =>
if(!repositoryInfo.repository.isPrivate || isWritableUser(user, repositoryInfo)){ if(!repositoryInfo.repository.`private` || isWritableUser(user, repositoryInfo)){
using(Git.open(getRepositoryDir(owner, repoName))) { git => using(Git.open(getRepositoryDir(owner, repoName))) { git =>
val repository = git.getRepository val repository = git.getRepository
val upload = new UploadPack(repository) val upload = new UploadPack(repository)

View File

@@ -17,7 +17,7 @@ trait OneselfAuthenticator { self: ControllerBase =>
{ {
defining(request.paths){ paths => defining(request.paths){ paths =>
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action case Some(x) if(x.administrator) => action
case Some(x) if(paths(0) == x.userName) => action case Some(x) if(paths(0) == x.userName) => action
case _ => Unauthorized() case _ => Unauthorized()
} }
@@ -38,10 +38,10 @@ trait OwnerAuthenticator { self: ControllerBase with RepositoryService with Acco
defining(request.paths){ paths => defining(request.paths){ paths =>
getRepository(paths(0), paths(1)).map { repository => getRepository(paths(0), paths(1)).map { repository =>
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action(repository) case Some(x) if(x.administrator) => action(repository)
case Some(x) if(repository.owner == x.userName) => action(repository) case Some(x) if(repository.owner == x.userName) => action(repository)
case Some(x) if(getGroupMembers(repository.owner).exists { member => case Some(x) if(getGroupMembers(repository.owner).exists { member =>
member.userName == x.userName && member.isManager == true member.userName == x.userName && member.manager == true
}) => action(repository) }) => action(repository)
case _ => Unauthorized() case _ => Unauthorized()
} }
@@ -78,7 +78,7 @@ trait AdminAuthenticator { self: ControllerBase =>
private def authenticate(action: => Any) = { private def authenticate(action: => Any) = {
{ {
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action case Some(x) if(x.administrator) => action
case _ => Unauthorized() case _ => Unauthorized()
} }
} }
@@ -97,7 +97,7 @@ trait CollaboratorsAuthenticator { self: ControllerBase with RepositoryService =
defining(request.paths){ paths => defining(request.paths){ paths =>
getRepository(paths(0), paths(1)).map { repository => getRepository(paths(0), paths(1)).map { repository =>
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action(repository) case Some(x) if(x.administrator) => action(repository)
case Some(x) if(paths(0) == x.userName) => action(repository) case Some(x) if(paths(0) == x.userName) => action(repository)
case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository) case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository)
case _ => Unauthorized() case _ => Unauthorized()
@@ -119,11 +119,11 @@ trait ReferrerAuthenticator { self: ControllerBase with RepositoryService =>
{ {
defining(request.paths){ paths => defining(request.paths){ paths =>
getRepository(paths(0), paths(1)).map { repository => getRepository(paths(0), paths(1)).map { repository =>
if(!repository.repository.isPrivate){ if(!repository.repository.`private`){
action(repository) action(repository)
} else { } else {
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action(repository) case Some(x) if(x.administrator) => action(repository)
case Some(x) if(paths(0) == x.userName) => action(repository) case Some(x) if(paths(0) == x.userName) => action(repository)
case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository) case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository)
case _ => Unauthorized() case _ => Unauthorized()
@@ -147,8 +147,8 @@ trait ReadableUsersAuthenticator { self: ControllerBase with RepositoryService =
defining(request.paths){ paths => defining(request.paths){ paths =>
getRepository(paths(0), paths(1)).map { repository => getRepository(paths(0), paths(1)).map { repository =>
context.loginAccount match { context.loginAccount match {
case Some(x) if(x.isAdmin) => action(repository) case Some(x) if(x.administrator) => action(repository)
case Some(x) if(!repository.repository.isPrivate) => action(repository) case Some(x) if(!repository.repository.`private`) => action(repository)
case Some(x) if(paths(0) == x.userName) => action(repository) case Some(x) if(paths(0) == x.userName) => action(repository)
case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository) case Some(x) if(getCollaborators(paths(0), paths(1)).contains(x.userName)) => action(repository)
case _ => Unauthorized() case _ => Unauthorized()
@@ -171,7 +171,7 @@ trait GroupManagerAuthenticator { self: ControllerBase with AccountService =>
defining(request.paths){ paths => defining(request.paths){ paths =>
context.loginAccount match { context.loginAccount match {
case Some(x) if(getGroupMembers(paths(0)).exists { member => case Some(x) if(getGroupMembers(paths(0)).exists { member =>
member.userName == x.userName && member.isManager member.userName == x.userName && member.manager
}) => action }) => action
case _ => Unauthorized() case _ => Unauthorized()
} }

View File

@@ -30,7 +30,7 @@ trait Notifier extends RepositoryService with AccountService with IssuesService
) )
.distinct .distinct
.withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded .withFilter ( _ != context.loginAccount.get.userName ) // the operation in person is excluded
.foreach ( getAccountByUserName(_) filterNot (_.isGroupAccount) filterNot (LDAPUtil.isDummyMailAddress(_)) foreach (x => notify(x.mailAddress)) ) .foreach ( getAccountByUserName(_) filterNot (_.groupAccount) filterNot (LDAPUtil.isDummyMailAddress(_)) foreach (x => notify(x.mailAddress)) )
} }

View File

@@ -32,7 +32,7 @@
</ul> </ul>
@helper.html.account("memberName", 200) @helper.html.account("memberName", 200)
<input type="button" class="btn btn-default" value="Add" id="addMember"/> <input type="button" class="btn btn-default" value="Add" id="addMember"/>
<input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.isManager).mkString(",")"/> <input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.manager).mkString(",")"/>
<div> <div>
<span class="error" id="error-members"></span> <span class="error" id="error-members"></span>
</div> </div>
@@ -103,7 +103,7 @@ $(function(){
}); });
@members.map { member => @members.map { member =>
addMemberHTML('@member.userName', @member.isManager); addMemberHTML('@member.userName', @member.manager);
} }
function addMemberHTML(userName, isManager){ function addMemberHTML(userName, isManager){

View File

@@ -31,7 +31,7 @@
<div class="col-md-8"> <div class="col-md-8">
<ul class="nav nav-tabs" style="margin-bottom: 5px;"> <ul class="nav nav-tabs" style="margin-bottom: 5px;">
<li@if(active == "repositories"){ class="active"}><a href="@url(account.userName)?tab=repositories">Repositories</a></li> <li@if(active == "repositories"){ class="active"}><a href="@url(account.userName)?tab=repositories">Repositories</a></li>
@if(account.isGroupAccount){ @if(account.groupAccount){
<li@if(active == "members"){ class="active"}><a href="@url(account.userName)?tab=members">Members</a></li> <li@if(active == "members"){ class="active"}><a href="@url(account.userName)?tab=members">Members</a></li>
} else { } else {
<li@if(active == "activity"){ class="active"}><a href="@url(account.userName)?tab=activity">Public Activity</a></li> <li@if(active == "activity"){ class="active"}><a href="@url(account.userName)?tab=activity">Public Activity</a></li>
@@ -43,9 +43,9 @@
</div> </div>
</li> </li>
} }
@if(loginAccount.isDefined && account.isGroupAccount && isGroupManager){ @if(loginAccount.isDefined && account.groupAccount && isGroupManager){
<li class="pull-right"> <li class="pull-right">
<div class="button-group"> <div class="button-groRepiosup">
<a href="@url(account.userName)/_editgroup" class="btn btn-default">Edit Group</a> <a href="@url(account.userName)/_editgroup" class="btn btn-default">Edit Group</a>
</div> </div>
</li> </li>

View File

@@ -15,7 +15,7 @@
<div class="repository-content"> <div class="repository-content">
<div class="block-header"> <div class="block-header">
<a href="@url(repository)">@repository.name</a> <a href="@url(repository)">@repository.name</a>
@if(repository.repository.isPrivate){ @if(repository.repository.`private`){
<i class="octicon octicon-lock"></i> <i class="octicon octicon-lock"></i>
} }
</div> </div>

View File

@@ -13,7 +13,7 @@
<input type="text" name="userName" id="userName" class="form-control" value="@account.map(_.userName)"@if(account.isDefined){ readonly}/> <input type="text" name="userName" id="userName" class="form-control" value="@account.map(_.userName)"@if(account.isDefined){ readonly}/>
@if(account.isDefined){ @if(account.isDefined){
<label for="removed"> <label for="removed">
<input type="checkbox" name="removed" id="removed" value="true" @if(account.get.isRemoved){checked}/> <input type="checkbox" name="removed" id="removed" value="true" @if(account.get.removed){checked}/>
Disable Disable
</label> </label>
<div> <div>
@@ -53,10 +53,10 @@
<fieldset class="form-group"> <fieldset class="form-group">
<label class="strong">User Type:</label> <label class="strong">User Type:</label>
<label class="radio" for="userType_Normal"> <label class="radio" for="userType_Normal">
<input type="radio" name="isAdmin" id="userType_Normal" value="false"@if(account.isEmpty || !account.get.isAdmin){ checked}/> Normal <input type="radio" name="isAdmin" id="userType_Normal" value="false"@if(account.isEmpty || !account.get.administrator){ checked}/> Normal
</label> </label>
<label class="radio" for="userType_Admin"> <label class="radio" for="userType_Admin">
<input type="radio" name="isAdmin" id="userType_Admin" value="true"@if(account.isDefined && account.get.isAdmin){ checked}/> Administrator <input type="radio" name="isAdmin" id="userType_Admin" value="true"@if(account.isDefined && account.get.administrator){ checked}/> Administrator
</label> </label>
</fieldset> </fieldset>
<fieldset class="form-group"> <fieldset class="form-group">

View File

@@ -14,7 +14,7 @@
<input type="text" name="groupName" id="groupName" class="form-control" value="@account.map(_.userName)"@if(account.isDefined){ readonly}/> <input type="text" name="groupName" id="groupName" class="form-control" value="@account.map(_.userName)"@if(account.isDefined){ readonly}/>
@if(account.isDefined){ @if(account.isDefined){
<label for="removed"> <label for="removed">
<input type="checkbox" name="removed" id="removed" value="true" @if(account.get.isRemoved){checked}/> <input type="checkbox" name="removed" id="removed" value="true" @if(account.get.removed){checked}/>
Disable Disable
</label> </label>
} }
@@ -38,7 +38,7 @@
</ul> </ul>
@helper.html.account("memberName", 200) @helper.html.account("memberName", 200)
<input type="button" class="btn btn-default" value="Add" id="addMember"/> <input type="button" class="btn btn-default" value="Add" id="addMember"/>
<input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.isManager).mkString(",")"/> <input type="hidden" id="members" name="members" value="@members.map(member => member.userName + ":" + member.manager).mkString(",")"/>
<div> <div>
<span class="error" id="error-members"></span> <span class="error" id="error-members"></span>
</div> </div>
@@ -98,7 +98,7 @@ $(function(){
}); });
@members.map { member => @members.map { member =>
addMemberHTML('@member.userName', @member.isManager); addMemberHTML('@member.userName', @member.manager);
} }
function addMemberHTML(userName, isManager){ function addMemberHTML(userName, isManager){

View File

@@ -14,9 +14,9 @@
<table class="table table-bordered table-hover"> <table class="table table-bordered table-hover">
@users.map { account => @users.map { account =>
<tr> <tr>
<td @if(account.isRemoved){style="background-color: #dddddd;"}> <td @if(account.removed){style="background-color: #dddddd;"}>
<div class="pull-right"> <div class="pull-right">
@if(account.isGroupAccount){ @if(account.groupAccount){
<a href="@path/admin/users/@account.userName/_editgroup">Edit</a> <a href="@path/admin/users/@account.userName/_editgroup">Edit</a>
} else { } else {
<a href="@path/admin/users/@account.userName/_edituser">Edit</a> <a href="@path/admin/users/@account.userName/_edituser">Edit</a>
@@ -25,16 +25,16 @@
<div class="strong"> <div class="strong">
@avatar(account.userName, 20) @avatar(account.userName, 20)
<a href="@url(account.userName)">@account.userName</a> <a href="@url(account.userName)">@account.userName</a>
@if(account.isGroupAccount){ @if(account.groupAccount){
(Group) (Group)
} else { } else {
@if(account.isAdmin){ @if(account.administrator){
(Administrator) (Administrator)
} else { } else {
(Normal) (Normal)
} }
} }
@if(account.isGroupAccount){ @if(account.groupAccount){
@members(account.userName).map { userName => @members(account.userName).map { userName =>
@avatar(userName, 20, tooltip = true) @avatar(userName, 20, tooltip = true)
} }
@@ -42,7 +42,7 @@
</div> </div>
<div> <div>
<hr> <hr>
@if(!account.isGroupAccount){ @if(!account.groupAccount){
<i class="octicon octicon-mail"></i> @account.mailAddress <i class="octicon octicon-mail"></i> @account.mailAddress
} }
@account.url.map { url => @account.url.map { url =>
@@ -52,7 +52,7 @@
<div> <div>
<span class="muted">Registered:</span> @datetime(account.registeredDate) <span class="muted">Registered:</span> @datetime(account.registeredDate)
<span class="muted">Updated:</span> @datetime(account.updatedDate) <span class="muted">Updated:</span> @datetime(account.updatedDate)
@if(!account.isGroupAccount){ @if(!account.groupAccount){
<span class="muted">Last Login:</span> @account.lastLoginDate.map(datetime) <span class="muted">Last Login:</span> @account.lastLoginDate.map(datetime)
} }
</div> </div>

View File

@@ -2,7 +2,7 @@
@import gitbucket.core.service.RepositoryService @import gitbucket.core.service.RepositoryService
@import context._ @import context._
@import gitbucket.core.view.helpers._ @import gitbucket.core.view.helpers._
@if(repository.repository.isPrivate){ @if(repository.repository.`private`){
<i class="@{if(large){"mega-"}}octicon octicon-lock"></i> <i class="@{if(large){"mega-"}}octicon octicon-lock"></i>
} else { } else {
@if(repository.repository.originUserName.isDefined){ @if(repository.repository.originUserName.isDefined){

View File

@@ -36,7 +36,7 @@
<script src="@assets/vendors/facebox/facebox.js"></script> <script src="@assets/vendors/facebox/facebox.js"></script>
<script src="@assets/vendors/jquery-hotkeys/jquery.hotkeys.js"></script> <script src="@assets/vendors/jquery-hotkeys/jquery.hotkeys.js"></script>
@repository.map { repository => @repository.map { repository =>
@if(!repository.repository.isPrivate){ @if(!repository.repository.`private`){
<meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" /> <meta name="go-import" content="@context.baseUrl.replaceFirst("^https?://", "")/@repository.owner/@repository.name git @repository.httpUrl" />
} }
} }
@@ -92,7 +92,7 @@
<ul class="dropdown-menu pull-right"> <ul class="dropdown-menu pull-right">
<li><a href="@url(loginAccount.get.userName)">Your profile</a></li> <li><a href="@url(loginAccount.get.userName)">Your profile</a></li>
<li><a href="@url(loginAccount.get.userName)/_edit">Account settings</a></li> <li><a href="@url(loginAccount.get.userName)/_edit">Account settings</a></li>
@if(loginAccount.get.isAdmin){ @if(loginAccount.get.administrator){
<li><a href="@path/admin/users">System administration</a></li> <li><a href="@path/admin/users">System administration</a></li>
} }
<li><a href="@path/signout">Sign out</a></li> <li><a href="@path/signout">Sign out</a></li>

View File

@@ -63,7 +63,7 @@
@menuitem("/issues", "issues" , "issue-opened" , "Issues", repository.issueCount) @menuitem("/issues", "issues" , "issue-opened" , "Issues", repository.issueCount)
@menuitem("/pulls" , "pulls" , "git-pull-request" , "Pull Requests", repository.pullCount) @menuitem("/pulls" , "pulls" , "git-pull-request" , "Pull Requests", repository.pullCount)
@menuitem("/wiki" , "wiki" , "book" , "Wiki") @menuitem("/wiki" , "wiki" , "book" , "Wiki")
@if(loginAccount.isDefined && (loginAccount.get.isAdmin || repository.managers.contains(loginAccount.get.userName))){ @if(loginAccount.isDefined && (loginAccount.get.administrator || repository.managers.contains(loginAccount.get.userName))){
@menuitem("/settings" , "settings" , "tools", "Settings") @menuitem("/settings" , "settings" , "tools", "Settings")
} }
</ul> </ul>

View File

@@ -21,7 +21,7 @@
<fieldset class="margin"> <fieldset class="margin">
<label class="radio"> <label class="radio">
<input type="radio" name="isPrivate" value="false" <input type="radio" name="isPrivate" value="false"
@if(!repository.repository.isPrivate ){ checked } @if(!repository.repository.`private` ){ checked }
@if(repository.repository.parentUserName.isDefined){ disabled } @if(repository.repository.parentUserName.isDefined){ disabled }
> >
<span class="strong"><i class="octicon octicon-repo"></i> Public</span><br> <span class="strong"><i class="octicon octicon-repo"></i> Public</span><br>
@@ -31,7 +31,7 @@
</label> </label>
<label class="radio"> <label class="radio">
<input type="radio" name="isPrivate" value="true" <input type="radio" name="isPrivate" value="true"
@if(repository.repository.isPrivate ){ checked } @if(repository.repository.`private` ){ checked }
@if(repository.repository.parentUserName.isDefined){ disabled } @if(repository.repository.parentUserName.isDefined){ disabled }
> >
<span class="strong"><i class="octicon octicon-lock"></i> Private</span><br> <span class="strong"><i class="octicon octicon-lock"></i> Private</span><br>

View File

@@ -84,14 +84,14 @@ class AvatarImageProviderSpec extends FunSpec with MockitoSugar {
fullName = "user@localhost", fullName = "user@localhost",
mailAddress = "", mailAddress = "",
password = "", password = "",
isAdmin = false, administrator = false,
url = None, url = None,
registeredDate = new Date(), registeredDate = new Date(),
updatedDate = new Date(), updatedDate = new Date(),
lastLoginDate = None, lastLoginDate = None,
image = image, image = image,
isGroupAccount = false, groupAccount = false,
isRemoved = false) removed = false)
private def createSystemSettings(useGravatar: Boolean) = private def createSystemSettings(useGravatar: Boolean) =
SystemSettings( SystemSettings(