diff --git a/src/main/scala/gitbucket/core/controller/FileUploadController.scala b/src/main/scala/gitbucket/core/controller/FileUploadController.scala index d6213a2..e74f9d4 100644 --- a/src/main/scala/gitbucket/core/controller/FileUploadController.scala +++ b/src/main/scala/gitbucket/core/controller/FileUploadController.scala @@ -1,18 +1,24 @@ package gitbucket.core.controller -import gitbucket.core.util.{Keys, FileUtil} +import gitbucket.core.model.Account +import gitbucket.core.service.{AccountService, RepositoryService} +import gitbucket.core.servlet.Database +import gitbucket.core.util._ import gitbucket.core.util.ControlUtil._ import gitbucket.core.util.Directory._ +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.dircache.DirCache +import org.eclipse.jgit.lib.{FileMode, Constants} import org.scalatra._ import org.scalatra.servlet.{MultipartConfig, FileUploadSupport, FileItem} -import org.apache.commons.io.FileUtils +import org.apache.commons.io.{IOUtils, FileUtils} /** * Provides Ajax based file upload functionality. * * This servlet saves uploaded file. */ -class FileUploadController extends ScalatraServlet with FileUploadSupport { +class FileUploadController extends ScalatraServlet with FileUploadSupport with RepositoryService with AccountService { configureMultipartHandling(MultipartConfig(maxFileSize = Some(3 * 1024 * 1024))) @@ -31,6 +37,54 @@ }, FileUtil.isUploadableType) } + post("/wiki/:owner/:repository"){ + // Don't accept not logged-in users + session.get(Keys.Session.LoginAccount).collect { case loginAccount: Account => + val owner = params("owner") + val repository = params("repository") + + // Check whether logged-in user is collaborator + collaboratorsOnly(owner, repository, loginAccount){ + execute({ (file, fileId) => + val fileName = file.getName + LockUtil.lock(s"${owner}/${repository}/wiki") { + using(Git.open(Directory.getWikiRepositoryDir(owner, repository))) { git => + val builder = DirCache.newInCore.builder() + val inserter = git.getRepository.newObjectInserter() + val headId = git.getRepository.resolve(Constants.HEAD + "^{commit}") + + if(headId != null){ + JGitUtil.processTree(git, headId){ (path, tree) => + if(path != fileName){ + builder.add(JGitUtil.createDirCacheEntry(path, tree.getEntryFileMode, tree.getEntryObjectId)) + } + } + } + + val bytes = IOUtils.toByteArray(file.getInputStream) + builder.add(JGitUtil.createDirCacheEntry(fileName, FileMode.REGULAR_FILE, inserter.insert(Constants.OBJ_BLOB, bytes))) + builder.finish() + + val newHeadId = JGitUtil.createNewCommit(git, inserter, headId, builder.getDirCache.writeTree(inserter), + Constants.HEAD, loginAccount.userName, loginAccount.mailAddress, s"Uploaded ${fileName}") + + fileName + } + } + }, FileUtil.isImage) + } + } getOrElse BadRequest + } + + private def collaboratorsOnly(owner: String, repository: String, loginAccount: Account)(action: => Any): Any = { + implicit val session = Database.getSession(request) + loginAccount match { + case x if(x.isAdmin) => action + case x if(getCollaborators(owner, repository).contains(x.userName)) => action + case _ => BadRequest + } + } + private def execute(f: (FileItem, String) => Unit, mimeTypeChcker: (String) => Boolean) = fileParams.get("file") match { case Some(file) if(mimeTypeChcker(file.name)) => defining(FileUtil.generateFileId){ fileId => diff --git a/src/main/twirl/gitbucket/core/wiki/edit.scala.html b/src/main/twirl/gitbucket/core/wiki/edit.scala.html index 26ee0d3..8673e9e 100644 --- a/src/main/twirl/gitbucket/core/wiki/edit.scala.html +++ b/src/main/twirl/gitbucket/core/wiki/edit.scala.html @@ -1,8 +1,8 @@ @(pageName: String, page: Option[gitbucket.core.service.WikiService.WikiPageInfo], repository: gitbucket.core.service.RepositoryService.RepositoryInfo)(implicit context: gitbucket.core.controller.Context) -@import context._ @import gitbucket.core.view.helpers._ +@import gitbucket.core.util.FileUtil @html.main(s"${if(pageName.isEmpty) "New Page" else pageName} - ${repository.owner}/${repository.name}", Some(repository)){ @html.menu("wiki", repository){