(refs #115)Add repository permission checking

This commit is contained in:
takezoe
2014-03-11 02:30:11 +09:00
parent f78cdb637d
commit af0b52448a
2 changed files with 43 additions and 27 deletions

View File

@@ -9,7 +9,7 @@ import util.Directory._
import org.eclipse.jgit.transport.{ReceivePack, UploadPack} import org.eclipse.jgit.transport.{ReceivePack, UploadPack}
import org.apache.sshd.server.command.UnknownCommand import org.apache.sshd.server.command.UnknownCommand
import servlet.{Database, CommitLogHook} import servlet.{Database, CommitLogHook}
import service.SystemSettingsService import service.{AccountService, RepositoryService, SystemSettingsService}
import org.eclipse.jgit.errors.RepositoryNotFoundException import org.eclipse.jgit.errors.RepositoryNotFoundException
import javax.servlet.ServletContext import javax.servlet.ServletContext
@@ -18,8 +18,10 @@ object GitCommand {
val CommandRegex = """\Agit-(upload|receive)-pack '/([a-zA-Z0-9\-_.]+)/([a-zA-Z0-9\-_.]+).git'\Z""".r val CommandRegex = """\Agit-(upload|receive)-pack '/([a-zA-Z0-9\-_.]+)/([a-zA-Z0-9\-_.]+).git'\Z""".r
} }
abstract class GitCommand(val command: String) extends Command { abstract class GitCommand(val context: ServletContext, val command: String) extends Command {
protected val logger = LoggerFactory.getLogger(classOf[GitCommand]) self: RepositoryService with AccountService =>
private val logger = LoggerFactory.getLogger(classOf[GitCommand])
protected val (gitCommand, owner, repositoryName) = parseCommand protected val (gitCommand, owner, repositoryName) = parseCommand
protected var err: OutputStream = null protected var err: OutputStream = null
protected var in: InputStream = null protected var in: InputStream = null
@@ -30,6 +32,7 @@ abstract class GitCommand(val command: String) extends Command {
private def newTask(user: String): Runnable = new Runnable { private def newTask(user: String): Runnable = new Runnable {
override def run(): Unit = { override def run(): Unit = {
Database(context) withTransaction {
try { try {
runTask(user) runTask(user)
callback.onExit(0) callback.onExit(0)
@@ -43,6 +46,7 @@ abstract class GitCommand(val command: String) extends Command {
} }
} }
} }
}
override def start(env: Environment): Unit = { override def start(env: Environment): Unit = {
logger.info(s"start command : " + command) logger.info(s"start command : " + command)
@@ -80,36 +84,49 @@ abstract class GitCommand(val command: String) extends Command {
val repositoryName = split(1).substring(1, split(1).length - 5).split("/")(2) val repositoryName = split(1).substring(1, split(1).length - 5).split("/")(2)
(gitCommand, owner, repositoryName) (gitCommand, owner, repositoryName)
} }
protected def isWritableUser(username: String, repositoryInfo: RepositoryService.RepositoryInfo): Boolean =
getAccountByUserName(username) match {
case Some(account) => hasWritePermission(repositoryInfo.owner, repositoryInfo.name, Some(account))
case None => false
} }
class GitUploadPack(context: ServletContext, override val command: String) extends GitCommand(command: String) { }
class GitUploadPack(context: ServletContext, command: String) extends GitCommand(context, command)
with RepositoryService with AccountService {
override protected def runTask(user: String): Unit = { override protected def runTask(user: String): Unit = {
using(Git.open(getRepositoryDir(owner, repositoryName))) { getRepository(owner, repositoryName, null).foreach { repositoryInfo =>
git => if(!repositoryInfo.repository.isPrivate || isWritableUser(user, repositoryInfo)){
using(Git.open(getRepositoryDir(owner, repositoryName))) { git =>
val repository = git.getRepository val repository = git.getRepository
val upload = new UploadPack(repository) val upload = new UploadPack(repository)
upload.upload(in, out, err) upload.upload(in, out, err)
} }
} }
}
}
} }
class GitReceivePack(context: ServletContext, override val command: String) extends GitCommand(command: String) with SystemSettingsService { class GitReceivePack(context: ServletContext, command: String) extends GitCommand(context, command)
with SystemSettingsService with RepositoryService with AccountService {
// TODO Correct this info. where i get base url? // TODO Correct this info. where i get base url?
val BaseURL: String = loadSystemSettings().baseUrl.getOrElse("http://localhost:8080") val BaseURL: String = loadSystemSettings().baseUrl.getOrElse("http://localhost:8080")
override protected def runTask(user: String): Unit = { override protected def runTask(user: String): Unit = {
using(Git.open(getRepositoryDir(owner, repositoryName))) { getRepository(owner, repositoryName, null).foreach { repositoryInfo =>
git => if(isWritableUser(user, repositoryInfo)){
using(Git.open(getRepositoryDir(owner, repositoryName))) { git =>
val repository = git.getRepository val repository = git.getRepository
val receive = new ReceivePack(repository) val receive = new ReceivePack(repository)
receive.setPostReceiveHook(new CommitLogHook(owner, repositoryName, user, BaseURL)) receive.setPostReceiveHook(new CommitLogHook(owner, repositoryName, user, BaseURL))
Database(context) withTransaction {
receive.receive(in, out, err) receive.receive(in, out, err)
} }
} }
} }
}
} }

View File

@@ -16,7 +16,6 @@ class PublicKeyAuthenticator(context: ServletContext) extends PublickeyAuthentic
override def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean = { override def authenticate(username: String, key: PublicKey, session: ServerSession): Boolean = {
Database(context) withTransaction { Database(context) withTransaction {
// TODO Check permission to the repository here?
getPublicKeys(username).exists { sshKey => getPublicKeys(username).exists { sshKey =>
str2PublicKey(sshKey.publicKey) match { str2PublicKey(sshKey.publicKey) match {
case Some(publicKey) => key.equals(publicKey) case Some(publicKey) => key.equals(publicKey)