Browse Source

Create Backup funcitonality

Added create backup functionality to the admin panel
TheMardy 6 years ago
parent
commit
ef551f4cc6
3 changed files with 44 additions and 1 deletions
  1. 7 1
      src/api/admin.rs
  2. 20 0
      src/db/mod.rs
  3. 17 0
      src/static/templates/admin/page.hbs

+ 7 - 1
src/api/admin.rs

@@ -9,7 +9,7 @@ use rocket_contrib::json::Json;
 use crate::api::{ApiResult, EmptyResult, JsonResult};
 use crate::auth::{decode_admin, encode_jwt, generate_admin_claims, ClientIp};
 use crate::config::ConfigBuilder;
-use crate::db::{models::*, DbConn};
+use crate::db::{models::*, DbConn, backup_database};
 use crate::error::Error;
 use crate::mail;
 use crate::CONFIG;
@@ -30,6 +30,7 @@ pub fn routes() -> Vec<Route> {
         update_revision_users,
         post_config,
         delete_config,
+        backup_db,
     ]
 }
 
@@ -204,6 +205,11 @@ fn delete_config(_token: AdminToken) -> EmptyResult {
     CONFIG.delete_user_config()
 }
 
+#[post("/config/backup_db")]
+fn backup_db(_token: AdminToken) -> EmptyResult {
+    backup_database()
+}
+
 pub struct AdminToken {}
 
 impl<'a, 'r> FromRequest<'a, 'r> for AdminToken {

+ 20 - 0
src/db/mod.rs

@@ -9,6 +9,11 @@ use rocket::http::Status;
 use rocket::request::{self, FromRequest};
 use rocket::{Outcome, Request, State};
 
+use std::process::Command;
+use chrono::prelude::*;
+use crate::error::Error;
+
+
 use crate::CONFIG;
 
 /// An alias to the database connection used
@@ -34,6 +39,21 @@ pub fn get_connection() -> Result<Connection, ConnectionError> {
     Connection::establish(&CONFIG.database_url())
 }
 
+/// Creates a back-up of the database using sqlite3
+pub fn backup_database() -> Result<(), Error> {
+    let now: DateTime<Utc> = Utc::now();
+    let file_date = String::from(now.format("%Y%m%d").to_string());
+    let backup_command: String = format!("{}{}{}", ".backup 'db_", file_date, ".sqlite3'");
+
+    Command::new("sqlite3")
+        .current_dir("./data")
+        .args(&["db.sqlite3", &backup_command])
+        .output()
+        .expect("Can't open database, sqlite3 is not available, make sure it's installed and available on the PATH");
+
+    Ok(())
+}
+
 /// Attempts to retrieve a single connection from the managed database pool. If
 /// no pool is currently managed, fails with an `InternalServerError` status. If
 /// no connections are available, fails with a `ServiceUnavailable` status.

+ 17 - 0
src/static/templates/admin/page.hbs

@@ -154,6 +154,17 @@
                         {{/unless}}
                         {{/each}}
                         {{/each}}
+
+                    </div>
+                </div>
+                <div class="card bg-light mb-3">
+                    <div class="card-header"><button type="button" class="btn btn-link collapsed" data-toggle="collapse"
+                                                     data-target="#g_database">Database</button></div>
+                    <div id="g_database" class="card-body collapse" data-parent="#config-form">
+                        <div class="small mb-3">
+                            NOTE: A local installation of sqlite3 is required for this section to work.
+                        </div>
+                        <button type="button" class="btn btn-primary" onclick="backupDatabase();">Backup Database</button>
                     </div>
                 </div>
 
@@ -268,6 +279,12 @@
 
         return false;
     }
+    function backupDatabase() {
+        _post("/admin/config/backup_db",
+            "Backup created successfully",
+            "Error creating backup");
+        return false;
+    }
     function masterCheck(check_id, inputs_query) {
         function toggleEnabled(check_id, inputs_query, enabled) {
             $(inputs_query).prop("disabled", !enabled)