use stateful tokens
This commit is contained in:
parent
b70195bfe1
commit
f1f64665cc
13 changed files with 118 additions and 249 deletions
169
Cargo.lock
generated
169
Cargo.lock
generated
|
@ -115,12 +115,6 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.0"
|
||||
|
@ -163,12 +157,6 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
|
@ -262,7 +250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
|
||||
dependencies = [
|
||||
"aes-gcm",
|
||||
"base64 0.13.0",
|
||||
"base64",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"percent-encoding",
|
||||
|
@ -347,6 +335,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"diesel_derives",
|
||||
"libsqlite3-sys",
|
||||
"r2d2",
|
||||
|
@ -754,29 +743,6 @@ version = "1.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
|
||||
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 = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -918,7 +884,7 @@ dependencies = [
|
|||
"log",
|
||||
"memchr",
|
||||
"mime",
|
||||
"spin 0.9.3",
|
||||
"spin",
|
||||
"tokio",
|
||||
"tokio-util 0.6.9",
|
||||
"version_check",
|
||||
|
@ -938,7 +904,7 @@ name = "nomilo"
|
|||
version = "0.1.0-dev"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"base64 0.13.0",
|
||||
"base64",
|
||||
"chrono",
|
||||
"clap",
|
||||
"diesel",
|
||||
|
@ -946,13 +912,12 @@ dependencies = [
|
|||
"diesel_migrations",
|
||||
"figment",
|
||||
"humantime",
|
||||
"jsonwebtoken",
|
||||
"rand",
|
||||
"rocket",
|
||||
"rocket_sync_db_pools",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"toml",
|
||||
"trust-dns-client",
|
||||
"trust-dns-proto",
|
||||
"uuid",
|
||||
|
@ -967,17 +932,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -1116,17 +1070,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[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 = "2.1.0"
|
||||
|
@ -1337,21 +1280,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[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 0.5.2",
|
||||
"untrusted",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rocket"
|
||||
version = "0.5.0-rc.1"
|
||||
|
@ -1545,17 +1473,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[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.6"
|
||||
|
@ -1578,12 +1495,6 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.3"
|
||||
|
@ -1985,12 +1896,6 @@ 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 = "2.2.2"
|
||||
|
@ -2053,70 +1958,6 @@ version = "0.11.0+wasi-snapshot-preview1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -13,16 +13,15 @@ serde = { version = "1.0", features = ["derive"] }
|
|||
serde_json = "1.0"
|
||||
rocket = { git = "https://github.com/SergioBenitez/Rocket", rev = "6bdd2f8", version = "0.5.0-rc.1", features = ["json"] }
|
||||
rocket_sync_db_pools = { git = "https://github.com/SergioBenitez/Rocket", rev = "6bdd2f8", default-features = false, features = ["diesel_sqlite_pool"], version = "0.1.0-rc.1"}
|
||||
toml = "0.5"
|
||||
base64 = "0.13.0"
|
||||
uuid = { version = "0.8.2", features = ["v4", "serde"] }
|
||||
diesel = { version = "1.4", features = ["sqlite"] }
|
||||
diesel = { version = "1.4", features = ["sqlite", "chrono"] }
|
||||
diesel_migrations = "1.4"
|
||||
diesel-derive-enum = { version = "1", features = ["sqlite"] }
|
||||
jsonwebtoken = "7.2.0"
|
||||
chrono = { version = "0.4", features = ["serde"] }
|
||||
humantime = "2.1.0"
|
||||
tokio = "1"
|
||||
figment = { version = "0.10.6", features = ["toml", "env"] }
|
||||
clap = {version = "3", features = ["derive", "cargo"]}
|
||||
argon2 = "0.4.0"
|
||||
argon2 = {version = "0.4", default-features = false, features = ["alloc", "password-hash"] }
|
||||
rand = "0.8"
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
import_types = ["diesel::sql_types::*", "crate::models::users::*"]
|
||||
import_types = ["diesel::sql_types::*", "crate::models::user::*", "crate::models::auth::*"]
|
||||
|
|
2
migrations/2022-04-24-085505_session/down.sql
Normal file
2
migrations/2022-04-24-085505_session/down.sql
Normal file
|
@ -0,0 +1,2 @@
|
|||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE session;
|
8
migrations/2022-04-24-085505_session/up.sql
Normal file
8
migrations/2022-04-24-085505_session/up.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
-- Your SQL goes here
|
||||
CREATE TABLE session (
|
||||
`session_id` VARCHAR NOT NULL,
|
||||
`user_id` VARCHAR NOT NULL,
|
||||
`expires_at` VARCHAR NOT NULL,
|
||||
PRIMARY KEY(session_id),
|
||||
FOREIGN KEY(user_id) REFERENCES user(id)
|
||||
);
|
|
@ -2,8 +2,6 @@
|
|||
url = "db.sqlite"
|
||||
|
||||
[release.web_app]
|
||||
# base64 secret, change it (openssl rand -base64 32)
|
||||
secret = "Y2hhbmdlbWUK"
|
||||
token_duration = "1d"
|
||||
|
||||
[release.dns]
|
||||
|
|
|
@ -23,7 +23,6 @@ pub struct DnsClientConfig {
|
|||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct WebAppConfig {
|
||||
pub secret: String,
|
||||
#[serde(deserialize_with = "from_duration")]
|
||||
pub token_duration: Duration,
|
||||
}
|
||||
|
|
|
@ -1,63 +1,77 @@
|
|||
use uuid::Uuid;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use chrono::serde::ts_seconds;
|
||||
use chrono::prelude::{DateTime, Utc};
|
||||
use chrono::Duration;
|
||||
use jsonwebtoken::{
|
||||
encode, decode,
|
||||
Header, Validation,
|
||||
Algorithm as JwtAlgorithm, EncodingKey, DecodingKey,
|
||||
errors::Result as JwtResult
|
||||
};
|
||||
use chrono::naive::serde::ts_seconds::serialize as ts_seconds_naive;
|
||||
use chrono::{Duration, NaiveDateTime, Utc, DateTime};
|
||||
|
||||
use diesel::prelude::*;
|
||||
use rand::Rng;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::distributions::Alphanumeric;
|
||||
|
||||
use crate::models::user::UserInfo;
|
||||
use crate::schema::*;
|
||||
use crate::models::errors::UserError;
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct AuthClaims {
|
||||
pub jti: String,
|
||||
pub sub: String,
|
||||
#[serde(with = "ts_seconds")]
|
||||
pub exp: DateTime<Utc>,
|
||||
#[serde(with = "ts_seconds")]
|
||||
pub iat: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct AuthTokenResponse {
|
||||
pub token: String
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct AuthTokenRequest {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
impl AuthClaims {
|
||||
pub fn new(user_info: &UserInfo, token_duration: Duration) -> AuthClaims {
|
||||
let jti = Uuid::new_v4().to_simple().to_string();
|
||||
let iat = Utc::now();
|
||||
let exp = iat + token_duration;
|
||||
#[derive(Debug, Serialize, Queryable, Identifiable, Insertable)]
|
||||
#[table_name = "session"]
|
||||
#[primary_key(session_id)]
|
||||
pub struct Session {
|
||||
#[serde(rename = "token")]
|
||||
pub session_id: String,
|
||||
#[serde(skip)]
|
||||
pub user_id: String,
|
||||
#[serde(serialize_with = "ts_seconds_naive")]
|
||||
pub expires_at: NaiveDateTime,
|
||||
}
|
||||
|
||||
AuthClaims {
|
||||
jti,
|
||||
sub: user_info.id.clone(),
|
||||
exp,
|
||||
iat,
|
||||
}
|
||||
impl Session {
|
||||
pub fn generate_id() -> String {
|
||||
OsRng
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(50)
|
||||
.map(char::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn decode(token: &str, secret: &str) -> JwtResult<AuthClaims> {
|
||||
decode::<AuthClaims>(
|
||||
token,
|
||||
&DecodingKey::from_secret(secret.as_ref()),
|
||||
&Validation::new(JwtAlgorithm::HS256)
|
||||
).map(|data| data.claims)
|
||||
pub fn from_session_id(conn: &diesel::SqliteConnection, id: &str) -> Result<Session, UserError> {
|
||||
use crate::schema::session::dsl::*;
|
||||
session
|
||||
.find(id)
|
||||
.get_result(conn)
|
||||
.map_err(|_| UserError::ExpiredSession)
|
||||
.and_then(|s: Session| {
|
||||
let expires = DateTime::<Utc>::from_utc(s.expires_at, Utc);
|
||||
if expires < Utc::now() {
|
||||
Err(UserError::ExpiredSession)
|
||||
} else {
|
||||
Ok(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn encode(self, secret: &str) -> JwtResult<String> {
|
||||
encode(&Header::default(), &self, &EncodingKey::from_secret(secret.as_ref()))
|
||||
pub fn new(conn: &diesel::SqliteConnection, user_info: &UserInfo, token_duration: Duration) -> Result<Session, UserError> {
|
||||
use crate::schema::session::dsl::*;
|
||||
|
||||
let expires = Utc::now() + token_duration;
|
||||
|
||||
let user_session = Session {
|
||||
session_id: Session::generate_id(),
|
||||
user_id: user_info.id.clone(),
|
||||
expires_at: expires.naive_utc(),
|
||||
};
|
||||
|
||||
diesel::insert_into(session)
|
||||
.values(&user_session)
|
||||
.execute(conn)
|
||||
.map_err(UserError::DbError)?;
|
||||
|
||||
Ok(user_session)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub enum UserError {
|
|||
UserConflict,
|
||||
BadCreds,
|
||||
BadToken,
|
||||
ExpiredToken,
|
||||
ExpiredSession,
|
||||
MalformedHeader,
|
||||
PermissionDenied,
|
||||
DbError(DieselError),
|
||||
|
@ -91,7 +91,7 @@ impl From<UserError> for ErrorResponse {
|
|||
UserError::UserConflict => ErrorResponse::new(Status::Conflict, "This user already exists".into()),
|
||||
UserError::NotFound => ErrorResponse::new(Status::NotFound, "User does not exist".into()),
|
||||
UserError::BadToken => ErrorResponse::new(Status::BadRequest, "Malformed token".into()),
|
||||
UserError::ExpiredToken => ErrorResponse::new(Status::Unauthorized, "The provided token has expired".into()),
|
||||
UserError::ExpiredSession => ErrorResponse::new(Status::Unauthorized, "The provided session token has expired".into()),
|
||||
UserError::MalformedHeader => ErrorResponse::new(Status::BadRequest, "Malformed authorization header".into()),
|
||||
UserError::PermissionDenied => ErrorResponse::new(Status::Forbidden, "Bearer is not authorized to access the resource".into()),
|
||||
UserError::ZoneNotFound => ErrorResponse::new(Status::NotFound, "DNS zone does not exist".into()),
|
||||
|
|
|
@ -9,7 +9,7 @@ pub mod user;
|
|||
pub mod zone;
|
||||
|
||||
// Reexport types for convenience
|
||||
pub use auth::{AuthClaims, AuthTokenRequest, AuthTokenResponse};
|
||||
pub use auth::{AuthTokenRequest, Session};
|
||||
pub use class::DNSClass;
|
||||
pub use errors::{UserError, ErrorResponse, make_500};
|
||||
pub use name::{AbsoluteName, SerdeName};
|
||||
|
|
|
@ -2,23 +2,21 @@ use uuid::Uuid;
|
|||
use diesel::prelude::*;
|
||||
use diesel::result::Error as DieselError;
|
||||
use diesel_derive_enum::DbEnum;
|
||||
use rocket::{State, request::{FromRequest, Request, Outcome}};
|
||||
use rocket::request::{FromRequest, Request, Outcome};
|
||||
use rocket::outcome::try_outcome;
|
||||
use serde::{Deserialize};
|
||||
use argon2::password_hash::{PasswordHash, PasswordHasher, PasswordVerifier, SaltString};
|
||||
use argon2::password_hash::errors::Error as PasswordHashError;
|
||||
use argon2::password_hash::rand_core::OsRng;
|
||||
use rand::rngs::OsRng;
|
||||
use argon2::{Algorithm, Argon2, Version, Params};
|
||||
use jsonwebtoken::{
|
||||
errors::ErrorKind as JwtErrorKind
|
||||
};
|
||||
|
||||
|
||||
use crate::schema::*;
|
||||
use crate::DbConn;
|
||||
use crate::config::Config;
|
||||
|
||||
use crate::models::errors::{UserError, ErrorResponse, make_500};
|
||||
use crate::models::zone::Zone;
|
||||
use crate::models::auth::AuthClaims;
|
||||
use crate::models::auth::Session;
|
||||
|
||||
|
||||
const BEARER: &str = "Bearer ";
|
||||
|
@ -127,31 +125,24 @@ impl<'r> FromRequest<'r> for UserInfo {
|
|||
};
|
||||
|
||||
let token = if auth_header.starts_with(BEARER) {
|
||||
auth_header.trim_start_matches(BEARER)
|
||||
auth_header.trim_start_matches(BEARER).to_string()
|
||||
} else {
|
||||
return ErrorResponse::from(UserError::MalformedHeader).into()
|
||||
};
|
||||
|
||||
let config = try_outcome!(request.guard::<&State<Config>>().await.map_failure(make_500));
|
||||
let conn = try_outcome!(request.guard::<DbConn>().await.map_failure(make_500));
|
||||
|
||||
let token_data = AuthClaims::decode(
|
||||
token, &config.web_app.secret
|
||||
).map_err(|e| match e.into_kind() {
|
||||
JwtErrorKind::ExpiredSignature => UserError::ExpiredToken,
|
||||
_ => UserError::BadToken,
|
||||
});
|
||||
let session_res = conn.run(move |c| {
|
||||
Session::from_session_id(c, &token)
|
||||
}).await;
|
||||
|
||||
let token_data = match token_data {
|
||||
let session = match session_res {
|
||||
Err(e) => return ErrorResponse::from(e).into(),
|
||||
Ok(data) => data
|
||||
Ok(s) => s,
|
||||
};
|
||||
|
||||
let user_id = token_data.sub;
|
||||
|
||||
conn.run(move |c| {
|
||||
match LocalUser::get_user_by_uuid(c, &user_id) {
|
||||
Err(UserError::NotFound) => ErrorResponse::from(UserError::NotFound).into(),
|
||||
match LocalUser::get_user_by_uuid(c, &session.user_id) {
|
||||
Err(e) => ErrorResponse::from(e).into(),
|
||||
Ok(d) => Outcome::Success(d),
|
||||
}
|
||||
|
|
|
@ -12,17 +12,22 @@ pub async fn create_auth_token(
|
|||
conn: DbConn,
|
||||
config: &State<Config>,
|
||||
auth_request: Json<models::AuthTokenRequest>
|
||||
) -> Result<Json<models::AuthTokenResponse>, models::ErrorResponse> {
|
||||
) -> Result<Json<models::Session>, models::ErrorResponse> {
|
||||
|
||||
let user_info = conn.run(move |c| {
|
||||
models::LocalUser::get_user_by_creds(c, &auth_request.username, &auth_request.password)
|
||||
let session_duration = config.web_app.token_duration;
|
||||
|
||||
let session = conn.run(move |c| {
|
||||
let user_info = models::LocalUser::get_user_by_creds(
|
||||
c,
|
||||
&auth_request.username,
|
||||
&auth_request.password
|
||||
)?;
|
||||
|
||||
models::Session::new(c, &user_info, session_duration)
|
||||
}).await?;
|
||||
|
||||
let token = models::AuthClaims::new(&user_info, config.web_app.token_duration)
|
||||
.encode(&config.web_app.secret)
|
||||
.map_err(models::make_500)?;
|
||||
|
||||
Ok(Json(models::AuthTokenResponse { token }))
|
||||
Ok(Json(session))
|
||||
}
|
||||
|
||||
#[post("/users", data = "<user_request>")]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
table! {
|
||||
use diesel::sql_types::*;
|
||||
use crate::models::user::*;
|
||||
use crate::models::user::RoleMapping;
|
||||
|
||||
localuser (user_id) {
|
||||
user_id -> Text,
|
||||
|
@ -10,6 +10,16 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
use diesel::sql_types::*;
|
||||
|
||||
session (session_id) {
|
||||
session_id -> Text,
|
||||
user_id -> Text,
|
||||
expires_at -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
use diesel::sql_types::*;
|
||||
|
||||
|
@ -37,11 +47,13 @@ table! {
|
|||
}
|
||||
|
||||
joinable!(localuser -> user (user_id));
|
||||
joinable!(session -> user (user_id));
|
||||
joinable!(user_zone -> user (user_id));
|
||||
joinable!(user_zone -> zone (zone_id));
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
localuser,
|
||||
session,
|
||||
user,
|
||||
user_zone,
|
||||
zone,
|
||||
|
|
Loading…
Reference in a new issue