basic token generation
parent
84b1ce0823
commit
2b8df138e0
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.3.2"
|
||||
|
@ -54,6 +56,27 @@ dependencies = [
|
|||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.48"
|
||||
|
@ -110,6 +133,17 @@ version = "1.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
||||
[[package]]
|
||||
name = "blake2b_simd"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||
dependencies = [
|
||||
"arrayref",
|
||||
"arrayvec",
|
||||
"constant_time_eq",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
|
@ -119,12 +153,24 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
|
@ -146,6 +192,7 @@ dependencies = [
|
|||
"libc",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"serde",
|
||||
"time",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
@ -159,6 +206,12 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "constant_time_eq"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.11.4"
|
||||
|
@ -187,6 +240,17 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-mac"
|
||||
version = "0.10.0"
|
||||
|
@ -288,6 +352,20 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "djangohashers"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b101df5b2cab337a012f1a43d4a48810a81c10ea3b6bc73b456f5707c7b4325"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"constant_time_eq",
|
||||
"lazy_static",
|
||||
"rand",
|
||||
"regex",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endian-type"
|
||||
version = "0.1.2"
|
||||
|
@ -591,6 +669,29 @@ version = "0.4.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc15e39392125075f60c95ba416f5381ff6c3a948ff02ab12464715adf56c821"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jsonwebtoken"
|
||||
version = "7.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afabcc15e437a6484fc4f12d0fd63068fe457bf93f1c148d3d9649c60b103f32"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"pem",
|
||||
"ring",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"simple_asn1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
|
@ -774,8 +875,11 @@ name = "nomilo"
|
|||
version = "0.1.0-dev"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"chrono",
|
||||
"diesel",
|
||||
"diesel-derive-enum",
|
||||
"djangohashers",
|
||||
"jsonwebtoken",
|
||||
"rocket",
|
||||
"rocket_contrib",
|
||||
"serde",
|
||||
|
@ -813,6 +917,17 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
|
@ -842,6 +957,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
|
@ -895,6 +1016,17 @@ dependencies = [
|
|||
"yansi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pem"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd56cbd21fea48d0c440b41cd69c589faacade08c992d9a54e471b79d0fd13eb"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"once_cell",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
|
@ -1048,6 +1180,38 @@ dependencies = [
|
|||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.16.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"spin",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket"
|
||||
version = "0.4.7"
|
||||
|
@ -1129,6 +1293,18 @@ dependencies = [
|
|||
"unicode-xid 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"blake2b_simd",
|
||||
"constant_time_eq",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.5"
|
||||
|
@ -1209,6 +1385,17 @@ dependencies = [
|
|||
"opaque-debug",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692ca13de57ce0613a363c8c2f1de925adebc81b04c923ac60c5488bb44abe4b"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.2"
|
||||
|
@ -1232,6 +1419,12 @@ dependencies = [
|
|||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "state"
|
||||
version = "0.4.2"
|
||||
|
@ -1460,6 +1653,12 @@ dependencies = [
|
|||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "untrusted"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.7.2"
|
||||
|
@ -1528,6 +1727,70 @@ version = "0.10.2+wasi-snapshot-preview1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fe8f61dba8e5d645a4d8132dc7a0a66861ed5e1045d2c0ed940fab33bac0fbe"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "046ceba58ff062da072c7cb4ba5b22a37f00a302483f7e2a6cdc18fedbdc1fd3"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log 0.4.14",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ef9aa01d36cda046f797c57959ff5f3c615c9cc63997a8d545831ec7976819b"
|
||||
dependencies = [
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96eb45c1b2ee33545a813a92dbb53856418bf7eb54ab34f7f7ff1448a5b3735d"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.64",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7148f4696fb4960a346eaa60bbfb42a1ac4ebba21f750f75fc1375b098d5ffa"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59fe19d70f5dacc03f6e46777213facae5ac3801575d56ca6cbd4c93dcd12310"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
|
|
@ -11,10 +11,13 @@ trust-dns-client = "0.20.1"
|
|||
trust-dns-proto = "0.20.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
rocket = "0.4.7"
|
||||
rocket = "0.4"
|
||||
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"] }
|
||||
djangohashers = { version = "1.4.0", features = ["with_argon2"], default-features = false }
|
||||
jsonwebtoken = "7.2.0"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
-- Your SQL goes here
|
||||
CREATE TABLE localuser (
|
||||
user_id VARCHAR NOT NULL PRIMARY KEY,
|
||||
username VARCHAR NOT NULL,
|
||||
username VARCHAR NOT NULL UNIQUE,
|
||||
password VARCHAR NOT NULL,
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
);
|
||||
|
|
|
@ -1,15 +1,26 @@
|
|||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use rocket_contrib::json::Json;
|
||||
use diesel::prelude::*;
|
||||
use rocket::Response;
|
||||
use rocket::http::Status;
|
||||
use uuid::Uuid;
|
||||
use jsonwebtoken::{encode, Header, EncodingKey};
|
||||
use chrono::prelude::{DateTime, Utc};
|
||||
use chrono::Duration;
|
||||
use chrono::serde::ts_seconds;
|
||||
|
||||
use crate::DbConn;
|
||||
use crate::models::users::{UserInfo, LocalUser, User};
|
||||
use crate::models::errors::ErrorResponse;
|
||||
use crate::models::users::{LocalUser, CreateUserRequest};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct AuthClaims {
|
||||
jti: String,
|
||||
sub: String,
|
||||
exp: usize,
|
||||
iat: usize,
|
||||
#[serde(with = "ts_seconds")]
|
||||
exp: DateTime<Utc>,
|
||||
#[serde(with = "ts_seconds")]
|
||||
iat: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
|
@ -19,26 +30,35 @@ pub struct AuthTokenResponse {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct AuthTokenRequest {
|
||||
user: String,
|
||||
username: String,
|
||||
password: String,
|
||||
}
|
||||
|
||||
#[post("/users/me/token", data = "<auth_request>")]
|
||||
pub fn create_auth_token(conn: DbConn, auth_request: Json<AuthTokenRequest>) -> Json<AuthTokenResponse> {
|
||||
use crate::schema::localuser::dsl::*;
|
||||
use crate::schema::user::dsl::*;
|
||||
pub fn create_auth_token(conn: DbConn, auth_request: Json<AuthTokenRequest>) -> Result<Json<AuthTokenResponse>, ErrorResponse<()>> {
|
||||
let user_info = LocalUser::get_user_by_creds(&conn, &auth_request.username, &auth_request.password)?;
|
||||
let jti = Uuid::new_v4().to_simple().to_string();
|
||||
let iat = Utc::now();
|
||||
let exp = iat + Duration::minutes(1);
|
||||
|
||||
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() })
|
||||
let claims = AuthClaims {
|
||||
jti: jti,
|
||||
sub: user_info.id,
|
||||
exp: exp,
|
||||
iat: iat,
|
||||
};
|
||||
|
||||
// TODO: catch error
|
||||
let token = encode(&Header::default(), &claims, &EncodingKey::from_secret("changeme".as_ref())).unwrap();
|
||||
|
||||
Ok(Json(AuthTokenResponse { token }))
|
||||
}
|
||||
|
||||
/*
|
||||
GET /users -> list all users
|
||||
POST /users
|
||||
{
|
||||
provider: local
|
||||
...
|
||||
#[post("/users", data = "<user_request>")]
|
||||
pub fn create_user<'r>(conn: DbConn, user_request: Json<CreateUserRequest>) -> Result<Response<'r>, ErrorResponse<()>>{
|
||||
// TODO: Check current user if any to check if user has permission to create users (with or without role)
|
||||
let _user_info = LocalUser::create_user(&conn, user_request.into_inner())?;
|
||||
Response::build()
|
||||
.status(Status::Created)
|
||||
.ok()
|
||||
}
|
||||
/users/<uuid or me>/
|
||||
*/
|
||||
|
|
|
@ -8,9 +8,6 @@ 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;
|
||||
|
@ -66,5 +63,5 @@ fn main() {
|
|||
rocket::ignite()
|
||||
.manage(client)
|
||||
.attach(DbConn::fairing())
|
||||
.mount("/api/v1", routes![get_zone_records, create_auth_token]).launch();
|
||||
.mount("/api/v1", routes![get_zone_records, create_auth_token, create_user]).launch();
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use rocket::http::Status;
|
|||
use rocket::request::Request;
|
||||
use rocket::response::{self, Response, Responder};
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
use crate::models::users::UserError;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct ErrorResponse<T> {
|
||||
|
@ -53,3 +53,19 @@ impl<'r, T: Serialize> Responder<'r> for ErrorResponse<T> {
|
|||
Response::build_from(Json(self).respond_to(req)?).status(status).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UserError> for ErrorResponse<()> {
|
||||
fn from(e: UserError) -> Self {
|
||||
match e {
|
||||
UserError::NotFound => ErrorResponse::new(Status::Unauthorized, "Incorrect password or username.".into()),
|
||||
UserError::UserExists => ErrorResponse::new(Status::Conflict, "User already exists.".into()),
|
||||
UserError::DbError(e) => make_500(e),
|
||||
UserError::PasswordError(e) => make_500(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn make_500<E: std::fmt::Debug>(e: E) -> ErrorResponse<()> {
|
||||
println!("{:?}", e);
|
||||
ErrorResponse::new(Status::InternalServerError, "An unexpected error occured.".into())
|
||||
}
|
||||
|
|
|
@ -1,25 +1,32 @@
|
|||
use uuid::Uuid;
|
||||
use diesel::prelude::*;
|
||||
use diesel::associations::HasTable;
|
||||
use diesel::result::Error as DieselError;
|
||||
use rocket::request::{FromRequest, Request, Outcome};
|
||||
use diesel_derive_enum::DbEnum;
|
||||
use serde::Deserialize;
|
||||
// TODO: Maybe just use argon2 crate directly
|
||||
use djangohashers::{make_password_with_algorithm, check_password, HasherError, Algorithm};
|
||||
|
||||
use crate::schema::*;
|
||||
use crate::DbConn;
|
||||
|
||||
#[derive(Debug, DbEnum)]
|
||||
#[derive(Debug, DbEnum, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum Role {
|
||||
Admin,
|
||||
ZoneAdmin,
|
||||
}
|
||||
|
||||
#[derive(Debug, Queryable, Identifiable)]
|
||||
// TODO: Store Uuid instead of string??
|
||||
// TODO: Store role as Role and not String.
|
||||
#[derive(Debug, Queryable, Identifiable, Insertable)]
|
||||
#[table_name = "user"]
|
||||
pub struct User {
|
||||
pub id: String,
|
||||
pub role: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Queryable, Identifiable)]
|
||||
#[derive(Debug, Queryable, Identifiable, Insertable)]
|
||||
#[table_name = "localuser"]
|
||||
#[primary_key(user_id)]
|
||||
pub struct LocalUser {
|
||||
|
@ -28,21 +35,128 @@ pub struct LocalUser {
|
|||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct CreateUserRequest {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
pub email: String,
|
||||
pub role: Option<Role>
|
||||
}
|
||||
|
||||
// pub struct LdapUserAssociation {
|
||||
// user_id: Uuid,
|
||||
// ldap_id: String
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UserInfo {
|
||||
id: Uuid,
|
||||
role: Role,
|
||||
username: String,
|
||||
pub id: String,
|
||||
pub role: String,
|
||||
pub username: String,
|
||||
}
|
||||
|
||||
impl<'a, 'r> FromRequest<'a, 'r> for UserInfo {
|
||||
type Error = ();
|
||||
|
||||
fn from_request(request: &'a Request<'r>) -> Outcome<UserInfo, ()> {
|
||||
// LocalUser::get_user_by_uuid()
|
||||
Outcome::Forward(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UserError {
|
||||
NotFound,
|
||||
UserExists,
|
||||
DbError(DieselError),
|
||||
PasswordError(HasherError),
|
||||
}
|
||||
|
||||
impl From<DieselError> for UserError {
|
||||
fn from(e: DieselError) -> Self {
|
||||
match e {
|
||||
DieselError::NotFound => UserError::NotFound,
|
||||
DieselError::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, _) => UserError::UserExists,
|
||||
other => UserError::DbError(other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HasherError> for UserError {
|
||||
fn from(e: HasherError) -> Self {
|
||||
match e {
|
||||
other => UserError::PasswordError(other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl LocalUser {
|
||||
pub fn create_user(conn: &DbConn, user_request: CreateUserRequest) -> Result<UserInfo, UserError> {
|
||||
use crate::schema::localuser::dsl::*;
|
||||
use crate::schema::user::dsl::*;
|
||||
|
||||
let new_user_id = Uuid::new_v4().to_simple().to_string();
|
||||
|
||||
let new_user = User {
|
||||
id: new_user_id.clone(),
|
||||
// TODO: Use role from request
|
||||
role: "zoneadmin".into(),
|
||||
};
|
||||
|
||||
let new_localuser = LocalUser {
|
||||
user_id: new_user_id.clone(),
|
||||
username: user_request.username.clone(),
|
||||
password: make_password_with_algorithm(&user_request.password, Algorithm::Argon2),
|
||||
};
|
||||
|
||||
let res = UserInfo {
|
||||
id: new_user.id.clone(),
|
||||
role: new_user.role.clone(),
|
||||
username: new_localuser.username.clone(),
|
||||
};
|
||||
|
||||
conn.immediate_transaction(|| -> diesel::QueryResult<()> {
|
||||
diesel::insert_into(user)
|
||||
.values(new_user)
|
||||
.execute(&**conn)?;
|
||||
|
||||
diesel::insert_into(localuser)
|
||||
.values(new_localuser)
|
||||
.execute(&**conn)?;
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn get_user_by_creds(
|
||||
conn: &DbConn,
|
||||
request_username: &str,
|
||||
request_password: &str
|
||||
) -> Result<UserInfo, UserError> {
|
||||
|
||||
use crate::schema::localuser::dsl::*;
|
||||
use crate::schema::user::dsl::*;
|
||||
|
||||
let (client_user, client_localuser): (User, LocalUser) = user.inner_join(localuser)
|
||||
.filter(username.eq(request_username))
|
||||
.get_result(&**conn)?;
|
||||
|
||||
if !check_password(&request_password, &client_localuser.password)? {
|
||||
return Err(UserError::NotFound);
|
||||
}
|
||||
|
||||
Ok(UserInfo {
|
||||
id: client_user.id,
|
||||
role: client_user.role,
|
||||
username: client_localuser.username,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_user_by_uuid(user_id: Uuid) -> Result<UserInfo, ()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue