1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::forms::project_form::ProjectForm;
use crate::util::ctx::add_flash;

use actix_session::Session;
use actix_web::web::{Data, Form, Path};
use actix_web::{HttpRequest, HttpResponse};
use serde::Deserialize;

use dbui_core::database::conn::{ConnectionParams, DatabaseEngine};
use dbui_core::Project;

use dbui_service::AppConfig;

/// Available at `/project/new`
pub fn new_project(session: Session, cfg: Data<AppConfig>, req: HttpRequest) -> HttpResponse {
  crate::act(&session, &cfg, req, |ctx, router| {
    let p = dbui_core::Project::new("".into(), "New".into(), dbui_core::database::conn::ConnectionParams::default());
    dbui_templates::project::project_edit::edit(&ctx, router, &p, true)
  })
}

/// Available by posting to `/project/new`
pub fn create(session: Session, cfg: Data<AppConfig>, form: Option<Form<ProjectForm>>, req: HttpRequest) -> HttpResponse {
  match form {
    Some(f) => crate::redir(&session, &cfg, req, |ctx, router| {
      let p = f.as_project();
      add_flash(&session, ctx.log(), "success", &format!("Project [{}] changes saved", p.key()));
      cfg.set_project(&p)?;
      router.route("home", &[&f.key()])
    }),
    None => crate::redir(&session, &cfg, req, |ctx, router| {
      add_flash(&session, ctx.log(), "error", "Invalid form (details soon)");
      router.route("project.detail", &[&"ERROR"])
    })
  }
}

/// Available at `/project/{key}`
pub fn detail(session: Session, cfg: Data<AppConfig>, key: Path<String>, req: HttpRequest) -> HttpResponse {
  crate::act(&session, &cfg, req, |ctx, router| {
    let p = ctx.app().get_project(&key)?;
    dbui_templates::project::project_detail::detail(&ctx, router, &p)
  })
}

/// Available at `/project/{key}/edit`
pub fn edit(session: Session, cfg: Data<AppConfig>, key: Path<String>, req: HttpRequest) -> HttpResponse {
  crate::act(&session, &cfg, req, |ctx, router| {
    let p = ctx.app().get_project(&key)?;
    dbui_templates::project::project_edit::edit(&ctx, router, &p, false)
  })
}

/// Available by posting to `/project/{key}/edit`
pub fn save(session: Session, cfg: Data<AppConfig>, key: Path<String>, form: Option<Form<ProjectForm>>, req: HttpRequest) -> HttpResponse {
  match form {
    Some(f) => crate::redir(&session, &cfg, req, |ctx, router| {
      let p = encrypt_pw(f.as_project());
      add_flash(&session, ctx.log(), "success", &format!("Project [{}] changes saved", p.key()));
      let k: &str = &key;
      if p.key() != k {
        cfg.remove_project(k)?;
      }
      cfg.set_project(&p)?;
      router.route("home", &[&p.key()])
    }),
    None => crate::redir(&session, &cfg, req, |ctx, router| {
      add_flash(&session, ctx.log(), "error", "Invalid form (details soon)");
      router.route("home", &[&key])
    })
  }
}

fn encrypt_pw(p: Project) -> Project {
  match p.conn().password() {
    Some(pw) if pw.starts_with("=/=") => p,
    Some(pw) => {
      let enc = dbui_database::crypto::encrypt("dbui", pw);
      let conn = ConnectionParams::new(
        DatabaseEngine::Postgres,
        p.conn().server().into(),
        *p.conn().port(),
        p.conn().database().into(),
        p.conn().user().into(),
        Some(format!("=/={}", enc)),
        p.conn().tls()
      );
      Project::new(p.key().into(), p.name().into(), conn)
    }
    None => p
  }
}

#[derive(Debug, Deserialize)]
struct SqlRequest {
  sql: String
}