Commit b568116b authored by MrMan's avatar MrMan

Theoretically working user addition endpoint

parent 5b161afb
......@@ -1267,6 +1267,7 @@ dependencies = [
"clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"fern 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mail 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
"new-tokio-smtp 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -1275,6 +1276,7 @@ dependencies = [
"rusqlite 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"simple-signal 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
......
......@@ -23,6 +23,8 @@ actix-web = "0.7.2"
uuid = { version = "0.6", features = ["v4"] }
rusqlite = { version = "0.13.0", features = ["bundled"] }
simple-signal = "1.1.1"
futures = "0.1.25"
serde_json = "*"
[dev-dependencies]
tempfile = "3"
......
use std::fs::{create_dir_all, File, copy};
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, Child as ChildProcess};
use std::sync::mpsc::{channel, Sender, Receiver};
use askama::Template;
use chrono::prelude::Local;
use components::{Component, ChildProcessManager, HasReqRespCommandBus, ReqResp, ComponentCmd, Configurable, FileConfigurable, Error};
use components::db::{DB, Connectable, SupportsVAliasLookup, SupportsVMailboxLookup, SupportsCyrusAuth};
use config::{PostfixCfg, MilterCfg, SMTPTLSCfg, SMTPDTLSCfg, DBCfg, DBType};
use make_absolute_path;
use make_absolute_path_from_str;
use simple_signal::{Signal};
use simple_signal;
use std::fs::{create_dir_all, File, copy};
use std::io::Write;
use std::path::Path;
use std::process::{Command, Stdio, Child as ChildProcess};
use std::sync::mpsc::{channel, Sender, Receiver};
use components::db::*;
use components::*;
use config::{PostfixCfg, MilterCfg, SMTPTLSCfg, SMTPDTLSCfg, DBCfg, DBType};
use models::user::MailboxUser;
pub struct Postfix {
cfg: PostfixCfg,
......@@ -27,7 +30,10 @@ pub struct Postfix {
#[derive(Clone, Debug, Deserialize, Serialize)]
pub enum PostfixCmd {
Lifecycle(ComponentCmd)
Lifecycle(ComponentCmd),
// user management
CreateUser(MailboxUser),
}
impl Postfix {
......@@ -76,6 +82,18 @@ impl Component for Postfix {
break;
}
PostfixCmd::CreateUser(new_user) => {
debug!("creating new use {:?}", &new_user);
// Attempt to add the new user
let result = self.db.add_mailbox_user(new_user);
// respond if a repsonse channel was provided
if let Some(chan) = req.response_chan {
let _ = chan.send(Box::new(result.unwrap()));
};
}
}
},
......
use actix_web::error::ErrorNotImplemented;
use actix_web::error::*;
use actix_web::http::Method;
use actix_web::{App, HttpRequest, Json, Result, Path};
use actix_web::{App, HttpRequest, HttpResponse, Json, Result, Path, FromRequest};
use components::ReqResp;
use components::postfix::PostfixCmd;
use components::web_admin::AppState;
use models::user::MailboxUser;
use std::sync::mpsc::Sender;
use std::sync::mpsc::{channel, Sender};
use futures::future::Future;
use std::time::Duration;
use serde_json::json;
const DEFAULT_OPERATION_TIMEOUT: Duration = Duration::from_secs(1);
pub fn app(
postfix_tx: Sender<ReqResp<PostfixCmd>>
......@@ -18,7 +23,7 @@ pub fn app(
.prefix("/api/v1")
.resource("/", |r| r.f(api_index))
.resource("/components/{name}/status", |r| r.method(Method::GET).with(component_status))
.resource("/users", |r| r.method(Method::POST).with(add_user))
.resource("/users", |r| r.method(Method::POST).f(add_user))
}
......@@ -50,8 +55,31 @@ fn component_status(info: Path<String>) -> Result<Json<ComponentStatus>> {
}
/// Add a user
fn add_user(user: Json<MailboxUser>) -> Result<Json<MailboxUser>> {
fn add_user(req: &HttpRequest<AppState>) -> Result<HttpResponse> {
// Send a message to the postfix component to create the new user
let new_user = Json::<MailboxUser>::extract(req).wait()?.into_inner();
let (tx, rx) = channel();
let postfix_req = ReqResp::<PostfixCmd> {
msg: PostfixCmd::CreateUser(new_user),
response_chan: Some(tx),
};
// Wait for the response from postfix, which should contain the mailbox user
rx
.recv_timeout(DEFAULT_OPERATION_TIMEOUT)
.map(|b| match b.downcast::<MailboxUser>() {
Ok(u) => HttpResponse::Created().json(json!({
"status": "success",
"data": u,
})),
Err(_) => HttpResponse::InternalServerError().json(json!({
"status": "error",
"message": "Failed to create user",
})).into(),
// TODO: send a message with the new MailboxUser to the Postfix component
return Err(ErrorNotImplemented("not implemented yet"))
})
.map_err(|_| ErrorInternalServerError("Unexpected failure"))
}
......@@ -7,7 +7,6 @@ use components::web_admin::api::v1::{app as api_v1_app};
use components::web_admin::root::{app as root_app};
use components::{Component, ReqResp, ComponentCmd, Error};
use config::WebAdminCfg;
use models::user::MailboxUser;
use std::sync::mpsc::Sender;
#[allow(dead_code)]
......@@ -38,10 +37,11 @@ impl Component for WebAdmin {
fn start(&mut self) -> Result<(), Error> {
let address = format!("{}:{}", self.cfg.host, self.cfg.port);
let postfix_chan = self.postfix_tx_chan.clone();
server::new(|| {
server::new(move || {
vec![
api_v1_app(self.postfix_tx_chan.clone()),
api_v1_app(postfix_chan.clone()),
root_app(),
]
})
......
......@@ -8,14 +8,17 @@ pub mod models;
#[macro_use] extern crate log;
#[macro_use] extern crate serde_derive;
extern crate actix_web;
extern crate chrono;
extern crate clap;
extern crate fern;
extern crate futures;
extern crate rusqlite;
extern crate serde_json;
extern crate simple_signal;
extern crate toml;
extern crate uuid;
extern crate clap;
extern crate simple_signal;
use std::env;
use std::process;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment