Hashing passwords the first
This commit is contained in:
parent
c79988b90a
commit
30275673bc
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -237,6 +237,17 @@ version = "1.0.56"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
|
||||
|
||||
[[package]]
|
||||
name = "argon2"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a27e27b63e4a34caee411ade944981136fdfa535522dc9944d6700196cbd899f"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"blake2",
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.6"
|
||||
|
@ -369,6 +380,12 @@ version = "0.13.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
|
@ -1214,6 +1231,17 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "password-hash"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e029e94abc8fb0065241c308f1ac6bc8d20f450e8f7c5f0b25cd9b8d526ba294"
|
||||
dependencies = [
|
||||
"base64ct",
|
||||
"rand_core",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.7"
|
||||
|
@ -1728,9 +1756,9 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"actix-web",
|
||||
"anyhow",
|
||||
"argon2",
|
||||
"askama",
|
||||
"async-sqlx-session",
|
||||
"blake2",
|
||||
"chrono",
|
||||
"dotenv",
|
||||
"serde",
|
||||
|
|
|
@ -14,7 +14,7 @@ tracing-subscriber = "0.3"
|
|||
anyhow = "1.0"
|
||||
chrono = "0.4"
|
||||
dotenv = "0.15"
|
||||
blake2 = "0.10"
|
||||
argon2 = "0.4"
|
||||
askama = "0.11"
|
||||
actix-web = "4.0"
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ pub struct Config {
|
|||
pub listen_addr: SocketAddr,
|
||||
pub admin_pass: String,
|
||||
pub connection_string: String,
|
||||
pub secret: String,
|
||||
pub log_level: Option<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -17,16 +17,18 @@
|
|||
*/
|
||||
|
||||
use crate::templates;
|
||||
use argon2::PasswordHasher;
|
||||
use sqlx::postgres::{PgConnectOptions, PgConnectionInfo, PgPoolOptions};
|
||||
use sqlx::Executor;
|
||||
use sqlx::{ConnectOptions, PgPool};
|
||||
use tracing::info;
|
||||
use tracing::log::LevelFilter;
|
||||
use argon2::Argon2;
|
||||
|
||||
pub struct Database(PgPool);
|
||||
pub struct Database(PgPool, String);
|
||||
|
||||
impl Database {
|
||||
pub async fn connect(conn_string: &str) -> anyhow::Result<Self> {
|
||||
pub async fn connect(conn_string: &str, secret: &str) -> anyhow::Result<Self> {
|
||||
let mut connect_options: PgConnectOptions = conn_string.parse()?;
|
||||
connect_options.log_statements(LevelFilter::Debug);
|
||||
info!("Connecting to the database");
|
||||
|
@ -39,7 +41,7 @@ impl Database {
|
|||
);
|
||||
conn.execute(include_str!("sql/schema.sql")).await?;
|
||||
|
||||
Ok(Self(pool))
|
||||
Ok(Self(pool, secret.to_string()))
|
||||
}
|
||||
|
||||
pub fn pool(&self) -> PgPool {
|
||||
|
@ -65,4 +67,25 @@ impl Database {
|
|||
|
||||
templates::Tasks { tasks: vec }
|
||||
}
|
||||
|
||||
fn hash(&self, password: &str) -> Result<String, ()> {
|
||||
let argon2 = Argon2::default();
|
||||
let hash = argon2.hash_password(password.as_bytes(), &self.1);
|
||||
if let Ok(ref hash) = hash {
|
||||
if let Some(ref hash) = hash.hash {
|
||||
return Ok(hash.to_string());
|
||||
}
|
||||
}
|
||||
tracing::error!("Error hashing password: {:?}", hash);
|
||||
Err(())
|
||||
}
|
||||
|
||||
pub async fn register(&self, username: &str, password: &str) {
|
||||
let hash = self.hash(password);
|
||||
if let Err(ref e) = hash {
|
||||
return;
|
||||
}
|
||||
tracing::debug!("{}", hash.unwrap());
|
||||
// TODO: insert into DB
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
|
||||
info!(concat!("Initializing - tmtd ", env!("CARGO_PKG_VERSION")));
|
||||
let (ctx, _) = broadcast::channel(1);
|
||||
let database = Arc::new(Database::connect(&cfg.connection_string).await?);
|
||||
let database = Arc::new(Database::connect(&cfg.connection_string, &cfg.secret).await?);
|
||||
let session_store =
|
||||
PostgresSessionStore::from_client(database.pool()).with_table_name("sessions");
|
||||
session_store.migrate().await?;
|
||||
|
|
12
src/task.rs
12
src/task.rs
|
@ -37,3 +37,15 @@ pub struct SortTask {
|
|||
pub category: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Login {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Register {
|
||||
pub username: String,
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
|
|
|
@ -39,3 +39,13 @@ pub struct Task {
|
|||
|
||||
pub struct CreateTask();
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "login.html")]
|
||||
|
||||
pub struct Login();
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "register.html")]
|
||||
|
||||
pub struct Register();
|
||||
|
||||
|
|
35
src/web.rs
35
src/web.rs
|
@ -36,6 +36,10 @@ impl App {
|
|||
.route(web::get().to(task)),
|
||||
web::resource("/create")
|
||||
.route(web::get().to(create)),
|
||||
web::resource("/login")
|
||||
.route(web::get().to(login)),
|
||||
web::resource("/register")
|
||||
.route(web::get().to(register)),
|
||||
web::resource("/api/task/create")
|
||||
.app_data(web::Data::new(db.clone()))
|
||||
.route(web::post().to(create_task)),
|
||||
|
@ -45,6 +49,12 @@ impl App {
|
|||
web::resource("/api/task/sort")
|
||||
.app_data(web::Data::new(db.clone()))
|
||||
.route(web::post().to(sort_task)),
|
||||
web::resource("/api/login")
|
||||
.app_data(web::Data::new(db.clone()))
|
||||
.route(web::post().to(login_user)),
|
||||
web::resource("/api/register")
|
||||
.app_data(web::Data::new(db.clone()))
|
||||
.route(web::post().to(register_user)),
|
||||
))
|
||||
})
|
||||
.bind(addr)?
|
||||
|
@ -65,6 +75,18 @@ async fn create() -> impl Responder {
|
|||
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
||||
}
|
||||
|
||||
async fn login() -> impl Responder {
|
||||
let login = templates::Login{};
|
||||
let html = login.render().unwrap();
|
||||
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
||||
}
|
||||
|
||||
async fn register() -> impl Responder {
|
||||
let register = templates::Register{};
|
||||
let html = register.render().unwrap();
|
||||
HttpResponseBuilder::new(StatusCode::OK).body(html)
|
||||
}
|
||||
|
||||
async fn create_task(req: web::Form<task::CreateTask>, db: web::Data<Arc<Database>>) -> impl Responder {
|
||||
tracing::debug!("Got POST request on /api/task/create: {:#?}", req);
|
||||
HttpResponse::SeeOther().insert_header(("Location", "/task")).finish()
|
||||
|
@ -79,3 +101,16 @@ async fn sort_task(req: web::Form<task::SortTask>, db: web::Data<Arc<Database>>)
|
|||
tracing::debug!("Got POST request on /api/task/sort: {:#?}", req);
|
||||
HttpResponse::SeeOther().insert_header(("Location", "/task")).finish()
|
||||
}
|
||||
|
||||
async fn login_user(req: web::Form<task::Login>, db: web::Data<Arc<Database>>) -> impl Responder {
|
||||
tracing::debug!("Got POST request on /api/login");
|
||||
HttpResponse::SeeOther().insert_header(("Location", "/task")).finish()
|
||||
}
|
||||
|
||||
async fn register_user(req: web::Form<task::Register>, db: web::Data<Arc<Database>>) -> impl Responder {
|
||||
tracing::debug!("Got POST request on /api/register");
|
||||
let db = db.clone();
|
||||
db.register(&req.username, &req.password).await;
|
||||
HttpResponse::SeeOther().insert_header(("Location", "/task")).finish()
|
||||
}
|
||||
|
||||
|
|
16
templates/login.html
Normal file
16
templates/login.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "navbar.html" %}
|
||||
|
||||
<form action="/api/login" method="post">
|
||||
<label for="Username">Username</label><br>
|
||||
<input type="text" id="username" name="username" style="width:fit-content"><br>
|
||||
<label for="Password">Password</label><br>
|
||||
<input type="password" id="password" name="password" style="width:fit-content"><br>
|
||||
<input type="submit" value="Login"><br>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
|
@ -1,10 +1,19 @@
|
|||
logo or something<br>
|
||||
navbar<br>
|
||||
|
||||
<a href="/">home</a> |
|
||||
<a href="/task">tasks</a> |
|
||||
<a href="/users">users</a> |
|
||||
<a href="/admin">admin panel</a>
|
||||
<div>
|
||||
<span style="float:left">
|
||||
<a href="/">home</a> |
|
||||
<a href="/task">tasks</a> |
|
||||
<a href="/users">users</a> |
|
||||
<a href="/admin">admin panel</a>
|
||||
</span>
|
||||
<span style="float:right">
|
||||
<a href="/login">login</a> |
|
||||
<a href="/register">register</a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
|
||||
|
|
16
templates/register.html
Normal file
16
templates/register.html
Normal file
|
@ -0,0 +1,16 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% include "navbar.html" %}
|
||||
|
||||
<form action="/api/register" method="post">
|
||||
<label for="Username">Username</label><br>
|
||||
<input type="text" id="username" name="username" style="width:fit-content"><br>
|
||||
<label for="Password">Password</label><br>
|
||||
<input type="password" id="password" name="password" style="width:fit-content"><br>
|
||||
<input type="submit" value="Register"><br>
|
||||
</form>
|
||||
|
||||
{% endblock content %}
|
||||
|
|
@ -13,14 +13,13 @@
|
|||
<option value="Assigned">assigned</option>
|
||||
<option value="InProgress">in progreess</option>
|
||||
<option value="Done">done</option>
|
||||
<input type="hidden">
|
||||
<input type="submit" value="Select">
|
||||
</select>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- Some only selecting specific task code here, for smarter people then me -->
|
||||
|
||||
<ul>
|
||||
{% for task in tasks %}
|
||||
{% include "task/task.html" %}
|
||||
|
|
Loading…
Reference in a new issue