All Downloads are FREE. Search and download functionalities are using the official Maven repository.

gitbucket.core.controller.FileUploadController.scala Maven / Gradle / Ivy

package gitbucket.core.controller

import gitbucket.core.model.Account
import gitbucket.core.service.RepositoryService.RepositoryInfo
import gitbucket.core.service.{AccountService, RepositoryService}
import gitbucket.core.servlet.Database
import gitbucket.core.util._
import gitbucket.core.util.SyntaxSugars._
import gitbucket.core.util.Directory._
import gitbucket.core.util.Implicits._
import org.eclipse.jgit.api.Git
import org.eclipse.jgit.dircache.DirCache
import org.eclipse.jgit.lib.{Constants, FileMode}
import org.scalatra._
import org.scalatra.servlet.{FileItem, FileUploadSupport, MultipartConfig}
import org.apache.commons.io.{FileUtils, IOUtils}

/**
 * Provides Ajax based file upload functionality.
 *
 * This servlet saves uploaded file.
 */
class FileUploadController extends ScalatraServlet with FileUploadSupport with RepositoryService with AccountService {

  configureMultipartHandling(MultipartConfig(maxFileSize = Some(3 * 1024 * 1024)))

  post("/image"){
    execute({ (file, fileId) =>
      FileUtils.writeByteArrayToFile(new java.io.File(getTemporaryDir(session.getId), fileId), file.get)
      session += Keys.Session.Upload(fileId) -> file.name
    }, FileUtil.isImage)
  }

  post("/file/:owner/:repository"){
    execute({ (file, fileId) =>
      FileUtils.writeByteArrayToFile(new java.io.File(
        getAttachedDir(params("owner"), params("repository")),
        fileId + "." + FileUtil.getExtension(file.getName)), file.get)
    }, 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
      onlyWikiEditable(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.isUploadableType)
      }
    } getOrElse BadRequest()
  }

  post("/import") {
    import JDBCUtil._
    session.get(Keys.Session.LoginAccount).collect { case loginAccount: Account if loginAccount.isAdmin =>
      execute({ (file, fileId) =>
        request2Session(request).conn.importAsSQL(file.getInputStream)
      }, _ => true)
    }
    redirect("/admin/data")
  }

  private def onlyWikiEditable(owner: String, repository: String, loginAccount: Account)(action: => Any): Any = {
    implicit val session = Database.getSession(request)
    getRepository(owner, repository) match {
      case Some(x) => x.repository.options.wikiOption match {
        case "ALL"     if !x.repository.isPrivate => action
        case "PUBLIC"  if hasGuestRole(owner, repository, Some(loginAccount)) => action
        case "PRIVATE" if hasDeveloperRole(owner, repository, Some(loginAccount)) => action
        case _  => BadRequest()
      }
      case None => 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 =>
        f(file, fileId)
        Ok(fileId)
      }
    case _ => BadRequest()
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy