From 84b1ce0823aab0fcce942bab9c5e9f47be33aa27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Berthaud-M=C3=BCller?= Date: Fri, 26 Mar 2021 18:30:38 -0400 Subject: [PATCH] bootstrap database --- .gitignore | 1 + Cargo.lock | 154 ++++++++++++++++++ Cargo.toml | 5 +- Rocket.toml | 2 + diesel.toml | 5 + migrations/.gitkeep | 0 .../2021-03-26-164945_create_users/down.sql | 3 + .../2021-03-26-164945_create_users/up.sql | 12 ++ src/auth/mod.rs | 2 + src/auth/providers.rs | 12 ++ src/auth/routes.rs | 44 +++++ src/main.rs | 16 +- src/models/mod.rs | 1 + src/models/users.rs | 48 ++++++ src/schema.rs | 21 +++ 15 files changed, 324 insertions(+), 2 deletions(-) create mode 100644 Rocket.toml create mode 100644 diesel.toml create mode 100644 migrations/.gitkeep create mode 100644 migrations/2021-03-26-164945_create_users/down.sql create mode 100644 migrations/2021-03-26-164945_create_users/up.sql create mode 100644 src/auth/mod.rs create mode 100644 src/auth/providers.rs create mode 100644 src/auth/routes.rs create mode 100644 src/models/users.rs create mode 100644 src/schema.rs diff --git a/.gitignore b/.gitignore index 7f1788b..a631336 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target config.toml +db.sqlite diff --git a/Cargo.lock b/Cargo.lock index 8348136..b6b47f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,6 +244,41 @@ dependencies = [ "syn 0.15.44", ] +[[package]] +name = "diesel" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "047bfc4d5c3bd2ef6ca6f981941046113524b9a9f9a7cbdfdd7ff40f58e6f542" +dependencies = [ + "byteorder", + "diesel_derives", + "libsqlite3-sys", + "r2d2", +] + +[[package]] +name = "diesel-derive-enum" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703e71c268ea2d8da9c0ab0b40d8b217179ee622209c170875d24443193a0dfb" +dependencies = [ + "heck", + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.64", +] + +[[package]] +name = "diesel_derives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.9", + "syn 1.0.64", +] + [[package]] name = "digest" version = "0.9.0" @@ -526,6 +561,15 @@ dependencies = [ "libc", ] +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -581,6 +625,25 @@ version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" +[[package]] +name = "libsqlite3-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64d31059f22935e6c31830db5249ba2b7ecd54fd73a9909286f0a67aa55c2fbd" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "lock_api" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.3.9" @@ -711,6 +774,8 @@ name = "nomilo" version = "0.1.0-dev" dependencies = [ "base64 0.13.0", + "diesel", + "diesel-derive-enum", "rocket", "rocket_contrib", "serde", @@ -718,6 +783,7 @@ dependencies = [ "toml 0.5.8", "trust-dns-client", "trust-dns-proto", + "uuid", ] [[package]] @@ -782,6 +848,31 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi 0.3.9", +] + [[package]] name = "pear" version = "0.1.4" @@ -828,6 +919,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + [[package]] name = "polyval" version = "0.4.5" @@ -881,6 +978,17 @@ dependencies = [ "proc-macro2 1.0.24", ] +[[package]] +name = "r2d2" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545c5bc2b880973c9c10e4067418407a0ccaa3091781d1671d46eb35107cb26f" +dependencies = [ + "log 0.4.14", + "parking_lot", + "scheduled-thread-pool", +] + [[package]] name = "radix_trie" version = "0.2.1" @@ -982,13 +1090,28 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7954a707f9ca18aa74ca8c1f5d1f900f52a4dceb68e96e3112143f759cfd20e" dependencies = [ + "diesel", "log 0.4.14", "notify", + "r2d2", "rocket", + "rocket_contrib_codegen", "serde", "serde_json", ] +[[package]] +name = "rocket_contrib_codegen" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30deb6dec53b91fac3538a2a3935cf13e0f462745f9f33bf27bedffbe7265b5d" +dependencies = [ + "devise", + "quote 0.6.13", + "version_check 0.9.3", + "yansi", +] + [[package]] name = "rocket_http" version = "0.4.7" @@ -1027,6 +1150,21 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6f74fd1204073fa02d5d5d68bec8021be4c38690b61264b2fdb48083d0e7d7" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "serde" version = "1.0.124" @@ -1345,6 +1483,22 @@ dependencies = [ "percent-encoding 2.1.0", ] +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom", + "serde", +] + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + [[package]] name = "version_check" version = "0.1.5" diff --git a/Cargo.toml b/Cargo.toml index b4276fa..50c1fa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,9 @@ trust-dns-proto = "0.20.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" rocket = "0.4.7" -rocket_contrib = { version = "0.4", default-features = false, features = ["json"]} +rocket_contrib = { version = "0.4", default-features = false, features = ["json", "diesel_sqlite_pool"]} toml = "0.5" base64 = "0.13.0" +uuid = { version = "0.8.2", features = ["v4", "serde"] } +diesel = { version = "1.4", features = ["sqlite"] } +diesel-derive-enum = { version = "1", features = ["sqlite"] } diff --git a/Rocket.toml b/Rocket.toml new file mode 100644 index 0000000..4e9292a --- /dev/null +++ b/Rocket.toml @@ -0,0 +1,2 @@ +[global.databases] +db = { url = "db.sqlite" } diff --git a/diesel.toml b/diesel.toml new file mode 100644 index 0000000..92267c8 --- /dev/null +++ b/diesel.toml @@ -0,0 +1,5 @@ +# For documentation on how to configure this file, +# see diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" diff --git a/migrations/.gitkeep b/migrations/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/migrations/2021-03-26-164945_create_users/down.sql b/migrations/2021-03-26-164945_create_users/down.sql new file mode 100644 index 0000000..973d984 --- /dev/null +++ b/migrations/2021-03-26-164945_create_users/down.sql @@ -0,0 +1,3 @@ +-- This file should undo anything in `up.sql` +DROP TABLE localuser; +DROP TABLE user; diff --git a/migrations/2021-03-26-164945_create_users/up.sql b/migrations/2021-03-26-164945_create_users/up.sql new file mode 100644 index 0000000..0dbdbdc --- /dev/null +++ b/migrations/2021-03-26-164945_create_users/up.sql @@ -0,0 +1,12 @@ +-- Your SQL goes here +CREATE TABLE localuser ( + user_id VARCHAR NOT NULL PRIMARY KEY, + username VARCHAR NOT NULL, + password VARCHAR NOT NULL, + FOREIGN KEY(user_id) REFERENCES user(id) +); + +CREATE TABLE user ( + id VARCHAR NOT NULL PRIMARY KEY, + role VARCHAR NOT NULL +); diff --git a/src/auth/mod.rs b/src/auth/mod.rs new file mode 100644 index 0000000..0a2a180 --- /dev/null +++ b/src/auth/mod.rs @@ -0,0 +1,2 @@ +pub mod providers; +pub mod routes; diff --git a/src/auth/providers.rs b/src/auth/providers.rs new file mode 100644 index 0000000..65c3ad2 --- /dev/null +++ b/src/auth/providers.rs @@ -0,0 +1,12 @@ +// enum Providers { +// Ldap(LdapProvider), +// Local(LocalProvider), +// } + +// struct LdapProvider { +// user_filter: String, +// group_filter: String, +// // ... +// } + +// struct LocalProvider; diff --git a/src/auth/routes.rs b/src/auth/routes.rs new file mode 100644 index 0000000..d8b1fe5 --- /dev/null +++ b/src/auth/routes.rs @@ -0,0 +1,44 @@ +use serde::{Serialize, Deserialize}; +use rocket_contrib::json::Json; +use diesel::prelude::*; +use crate::DbConn; +use crate::models::users::{UserInfo, LocalUser, User}; + +#[derive(Debug, Serialize, Deserialize)] +struct AuthClaims { + jti: String, + sub: String, + exp: usize, + iat: usize, +} + +#[derive(Debug, Serialize)] +pub struct AuthTokenResponse { + token: String +} + +#[derive(Debug, Deserialize)] +pub struct AuthTokenRequest { + user: String, + password: String, +} + +#[post("/users/me/token", data = "")] +pub fn create_auth_token(conn: DbConn, auth_request: Json) -> Json { + use crate::schema::localuser::dsl::*; + use crate::schema::user::dsl::*; + + let client_user: Result<(User, LocalUser), _> = user.inner_join(localuser).filter(username.eq(&auth_request.user)).get_result(&*conn); + println!("{:?}", client_user); + Json(AuthTokenResponse { token: "".into() }) +} + +/* +GET /users -> list all users +POST /users +{ + provider: local + ... +} +/users// +*/ diff --git a/src/main.rs b/src/main.rs index 8ab80f1..bfb8332 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,16 @@ #![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate rocket; +#[macro_use] extern crate rocket_contrib; +#[macro_use] extern crate diesel; + use rocket::State; use rocket::http::Status; + use rocket_contrib::json::Json; +use rocket_contrib::databases::diesel as rocket_diesel; + +use diesel::prelude::*; use trust_dns_client::client::{Client, SyncClient}; use trust_dns_client::tcp::TcpClientConnection; @@ -12,10 +19,16 @@ use trust_dns_client::rr::{DNSClass, Name, RecordType}; mod models; mod config; +mod auth; +mod schema; use models::errors::ErrorResponse; +use auth::routes::*; +#[database("db")] +pub struct DbConn(diesel::SqliteConnection); + #[get("/zones//records")] fn get_zone_records(client: State>, zone: String) -> Result>, ErrorResponse<()>> { // TODO: Implement FromParam for Name @@ -52,5 +65,6 @@ fn main() { rocket::ignite() .manage(client) - .mount("/api/v1", routes![get_zone_records]).launch(); + .attach(DbConn::fairing()) + .mount("/api/v1", routes![get_zone_records, create_auth_token]).launch(); } diff --git a/src/models/mod.rs b/src/models/mod.rs index dbf31e3..dd71b7c 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,5 +1,6 @@ pub mod dns; pub mod errors; +pub mod users; pub mod trust_dns_types { pub use trust_dns_client::rr::rdata::{ diff --git a/src/models/users.rs b/src/models/users.rs new file mode 100644 index 0000000..6d113a6 --- /dev/null +++ b/src/models/users.rs @@ -0,0 +1,48 @@ +use uuid::Uuid; +use diesel::prelude::*; +use diesel::associations::HasTable; +use rocket::request::{FromRequest, Request, Outcome}; +use diesel_derive_enum::DbEnum; + +use crate::schema::*; + +#[derive(Debug, DbEnum)] +pub enum Role { + Admin, + ZoneAdmin, +} + +#[derive(Debug, Queryable, Identifiable)] +#[table_name = "user"] +pub struct User { + pub id: String, + pub role: String, +} + +#[derive(Debug, Queryable, Identifiable)] +#[table_name = "localuser"] +#[primary_key(user_id)] +pub struct LocalUser { + pub user_id: String, + pub username: String, + pub password: String, +} + +// pub struct LdapUserAssociation { +// user_id: Uuid, +// ldap_id: String +// } + +pub struct UserInfo { + id: Uuid, + role: Role, + username: String, +} + +impl<'a, 'r> FromRequest<'a, 'r> for UserInfo { + type Error = (); + + fn from_request(request: &'a Request<'r>) -> Outcome { + Outcome::Forward(()) + } +} diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..21093d7 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,21 @@ +table! { + localuser (user_id) { + user_id -> Text, + username -> Text, + password -> Text, + } +} + +table! { + user (id) { + id -> Text, + role -> Text, + } +} + +joinable!(localuser -> user (user_id)); + +allow_tables_to_appear_in_same_query!( + localuser, + user, +);