diff --git a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala index 157a584..c79d374 100644 --- a/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala +++ b/src/main/scala/gitbucket/core/controller/SystemSettingsController.scala @@ -1,5 +1,7 @@ package gitbucket.core.controller +import java.io.FileInputStream + import gitbucket.core.admin.html import gitbucket.core.service.{AccountService, SystemSettingsService, RepositoryService} import gitbucket.core.util.AdminAuthenticator @@ -11,7 +13,7 @@ import gitbucket.core.util.Directory._ import gitbucket.core.util.StringUtil._ import io.github.gitbucket.scalatra.forms._ -import org.apache.commons.io.FileUtils +import org.apache.commons.io.{IOUtils, FileUtils} import org.scalatra.i18n.Messages class SystemSettingsController extends SystemSettingsControllerBase @@ -74,6 +76,7 @@ case class PluginForm(pluginIds: List[String]) + case class DataExportForm(tableNames: List[String]) case class NewUserForm(userName: String, password: String, fullName: String, mailAddress: String, isAdmin: Boolean, @@ -268,6 +271,29 @@ } }) + get("/admin/data")(adminOnly { + import gitbucket.core.util.JDBCUtil._ + val session = request2Session(request) + html.data(session.conn.allTableNames()) + }) + + post("/admin/data")(adminOnly { + import gitbucket.core.util.JDBCUtil._ + val session = request2Session(request) + val file = session.conn.export(request.getParameterValues("tableNames").toSeq) + + contentType = "application/octet-stream" + response.setHeader("Content-Disposition", "attachment; filename=" + file.getName) + response.setContentLength(file.length.toInt) + + using(new FileInputStream(file)){ in => + IOUtils.copy(in, response.outputStream) + } + + () + }) + + private def members: Constraint = new Constraint(){ override def validate(name: String, value: String, messages: Messages): Option[String] = { if(value.split(",").exists { diff --git a/src/main/scala/gitbucket/core/util/JDBCUtil.scala b/src/main/scala/gitbucket/core/util/JDBCUtil.scala index fd65037..7c4d19c 100644 --- a/src/main/scala/gitbucket/core/util/JDBCUtil.scala +++ b/src/main/scala/gitbucket/core/util/JDBCUtil.scala @@ -1,6 +1,6 @@ package gitbucket.core.util -import java.io.FileOutputStream +import java.io._ import java.sql._ import java.text.SimpleDateFormat import ControlUtil._ @@ -60,18 +60,17 @@ } } - def export(targetTables: Seq[String]): Unit = { + def export(targetTables: Seq[String]): File = { val dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss") + val file = File.createTempFile("gitbucket-export-", ".sql") - using(new FileOutputStream("export.sql")) { out => + using(new FileOutputStream(file)) { out => val dbMeta = conn.getMetaData val allTablesInDatabase = allTablesOrderByDependencies(dbMeta) allTablesInDatabase.foreach { tableName => if (targetTables.contains(tableName)) { val sb = new StringBuilder() - sb.append("DELETE FROM ACCOUNT WHERE USER_NAME = 'root';\n") - select(s"SELECT * FROM ${tableName}") { rs => sb.append(s"INSERT INTO ${tableName} (") @@ -107,6 +106,8 @@ } } } + + file } def allTableNames(): Seq[String] = { diff --git a/src/main/twirl/gitbucket/core/admin/data.scala.html b/src/main/twirl/gitbucket/core/admin/data.scala.html new file mode 100644 index 0000000..7cfd903 --- /dev/null +++ b/src/main/twirl/gitbucket/core/admin/data.scala.html @@ -0,0 +1,28 @@ +@(tableNames: Seq[String])(implicit context: gitbucket.core.controller.Context) +@import context._ +@import gitbucket.core.view.helpers._ +@html.main("Data export / import"){ + @admin.html.menu("data") { +