From d5eb4cfac77883d5a4fe78b8a76c3efb67f611e2 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Thu, 6 Aug 2020 23:29:48 +0200 Subject: [PATCH 01/23] Add other fields to user struct and migration --- Cargo.lock | 1 + Cargo.toml | 4 +-- README.md | 2 +- migrations/2019-10-30-155718_schema/up.sql | 34 +++++++++++++++------- src/models/user.rs | 26 +++++++++++++---- 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55b6892b..560a7b54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -339,6 +339,7 @@ checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c" dependencies = [ "bitflags", "byteorder", + "chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", "diesel_derives", "pq-sys", "r2d2", diff --git a/Cargo.toml b/Cargo.toml index d1e3080a..db96ff57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,7 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" serde_urlencoded = "0.6" -diesel = { version = "1.4", features = ["postgres", "r2d2"] } +diesel = { version = "1.4", features = ["postgres", "r2d2", "chrono"] } diesel_migrations = "1.4" tempfile = "3.1" maplit = "1.0" @@ -28,6 +28,6 @@ parking_lot = { version = "0.11", features = ["nightly"] } thiserror = "1.0.20" [dependencies.rocket_contrib] -version="0.4.2" +version = "0.4.2" default-features = false features = ["json", "diesel_postgres_pool", "serve"] diff --git a/README.md b/README.md index ff06d26c..0c09ee66 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The name is open for discussion. ``` ZAUTH_ADMIN_PASSWORD=admin cargo run ``` - The server should then run on[localhost:8000](http://localhost:8000) and create + The server should then run on [localhost:8000](http://localhost:8000) and create an admin user with password 'admin'. You can now start developing! A good way to start is to look at the routes defined in the [controllers](./src/controllers/). diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 373cd789..d80d89ca 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -1,14 +1,26 @@ -CREATE TABLE users ( - id SERIAL PRIMARY KEY, - username VARCHAR(255) NOT NULL UNIQUE, - password VARCHAR(255) NOT NULL, - admin BOOLEAN NOT NULL DEFAULT false +CREATE TABLE users +( + id SERIAL PRIMARY KEY, + username VARCHAR(255) NOT NULL UNIQUE, + hashed_password VARCHAR(255) NOT NULL, + admin BOOLEAN NOT NULL DEFAULT false, + firstname VARCHAR(255) NOT NULL, + lastname VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, -- TO BE OR NOT TE UNIQUE? + ssh_key TEXT, + last_accessed_at DATETIME NOT NULL, + created_at DATETIME NOT NULL DEFAULT NOW() ); -CREATE TABLE clients ( - id SERIAL PRIMARY KEY, - name VARCHAR(255) NOT NULL UNIQUE, - secret VARCHAR(255) NOT NULL, - needs_grant BOOLEAN NOT NULL DEFAULT false, - redirect_uri_list TEXT NOT NULL DEFAULT '' +CREATE INDEX ix_user_username ON user (username); +CREATE INDEX ix_user_email ON user (email); + + +CREATE TABLE clients +( + id SERIAL PRIMARY KEY, + name VARCHAR(255) NOT NULL UNIQUE, + secret VARCHAR(255) NOT NULL, + needs_grant BOOLEAN NOT NULL DEFAULT false, + redirect_uri_list TEXT NOT NULL DEFAULT '' ); diff --git a/src/models/user.rs b/src/models/user.rs index 1775bc16..de023904 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -3,6 +3,7 @@ use crate::errors::{Result, ZauthError}; use crate::ConcreteConnection; use diesel::{self, prelude::*}; +use chrono::NaiveDateTime; use pwhash::bcrypt::{self, BcryptSetup}; const DEFAULT_COST: u32 = 11; @@ -15,11 +16,16 @@ const BCRYPT_SETUP: BcryptSetup = BcryptSetup { mod schema { table! { users { - id -> Integer, - username -> Text, - #[sql_name = "password"] - hashed_password -> Text, - admin -> Bool, + id -> Integer, + username -> Varchar, + hashed_password -> Varchar, + admin -> Bool, + firstname -> Varchar, + lastname -> Varchar, + email -> Varchar, + ssh_key -> Nullable, + last_accessed_at -> Datetime, + created_at -> Datetime, } } } @@ -28,10 +34,18 @@ mod schema { #[table_name = "users"] pub struct User { pub id: i32, + // validate to have at least 3 chars pub username: String, #[serde(skip)] // Let's not send our users their hashed password, shall we? pub hashed_password: String, pub admin: bool, + + pub firstname: String, + pub lastname: String, + pub email: String, + pub ssh_key: Option, + pub last_accessed_at: NaiveDateTime, + pub created_at: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -103,11 +117,13 @@ impl User { pub fn update(self, conn: &ConcreteConnection) -> Result { let id = self.id; + conn.transaction(|| { // Create a new user diesel::update(users::table.find(id)) .set(self) .execute(conn)?; + // Fetch the updated record users::table.find(id).first(conn) }) From e23cb75c505f0f4f8124de9dfe8bb31204cb5f9c Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 7 Aug 2020 01:01:00 +0200 Subject: [PATCH 02/23] Extend user change and creation forms and models --- src/lib.rs | 16 +++++++--- src/models/user.rs | 52 +++++++++++++++++++++++++-------- src/schema.rs | 1 + templates/pages/home.html | 22 +++++++------- templates/users/index.html | 33 +++++++++++++++++++++ templates/users/show.html | 60 +++++++++++++++++++++++++++++++++++--- 6 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 src/schema.rs diff --git a/src/lib.rs b/src/lib.rs index 6cbd14c5..fb09b307 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,16 +112,24 @@ fn assemble(rocket: Rocket) -> Rocket { .or_else(|_e| { User::create( NewUser { - username: String::from("admin"), - password: String::from(&pw), + username: String::from("admin"), + password: String::from(&pw), + firstname: String::from(""), + lastname: String::from(""), + email: String::from(""), + ssh_key: None, }, &conn, ) }) .and_then(|mut user| { user.change_with(UserChange { - username: None, - password: Some(pw), + username: None, + password: Some(pw), + firstname: None, + lastname: None, + email: None, + ssh_key: None, })?; user.admin = true; user.update(&conn) diff --git a/src/models/user.rs b/src/models/user.rs index de023904..ef140a81 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -3,7 +3,7 @@ use crate::errors::{Result, ZauthError}; use crate::ConcreteConnection; use diesel::{self, prelude::*}; -use chrono::NaiveDateTime; +use chrono::{NaiveDateTime, Utc}; use pwhash::bcrypt::{self, BcryptSetup}; const DEFAULT_COST: u32 = 11; @@ -50,21 +50,33 @@ pub struct User { #[derive(FromForm, Deserialize, Debug, Clone)] pub struct NewUser { - pub username: String, - pub password: String, + pub username: String, + pub password: String, + pub firstname: String, + pub lastname: String, + pub email: String, + pub ssh_key: Option, } #[table_name = "users"] #[derive(Serialize, Insertable, Debug, Clone)] struct NewUserHashed { - username: String, - hashed_password: String, + username: String, + hashed_password: String, + firstname: String, + lastname: String, + email: String, + last_accessed_at: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] pub struct UserChange { - pub username: Option, - pub password: Option, + pub username: Option, + pub password: Option, + pub firstname: Option, + pub lastname: Option, + pub email: Option, + pub ssh_key: Option, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -91,18 +103,22 @@ impl User { pub fn create(user: NewUser, conn: &ConcreteConnection) -> Result { let user = NewUserHashed { - username: user.username, - hashed_password: hash(&user.password)?, + username: user.username, + hashed_password: hash(&user.password).ok()?, + firstname: user.firstname, + lastname: user.lastname, + email: user.email, + last_accessed_at: Utc::now().naive_utc(), }; conn.transaction(|| { // Create a new user - diesel::insert_into(users::table) + diesel::insert_into(user::table) .values(&user) .execute(conn)?; // Fetch the last created user - let user = users::table.order(users::id.desc()).first(conn)?; - Ok(user) + users.order(user::id.desc()).first(conn) }) + .ok() } pub fn change_with(&mut self, change: UserChange) -> Result<()> { @@ -112,6 +128,18 @@ impl User { if let Some(password) = change.password { self.hashed_password = hash(&password)?; } + if let Some(firstname) = change.firstname { + self.firstname = firstname; + } + if let Some(lastname) = change.lastname { + self.lastname = lastname; + } + if let Some(email) = change.email { + self.email = email; + } + if let Some(ssh_key) = change.ssh_key { + self.ssh_key = Some(ssh_key); + } Ok(()) } diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1 @@ + diff --git a/templates/pages/home.html b/templates/pages/home.html index 8e54236a..a30535cb 100644 --- a/templates/pages/home.html +++ b/templates/pages/home.html @@ -2,22 +2,22 @@ {% block content %}

Welcome to the Zauth debug page

{% match current_user %} - {% when Some with (user) %} -

You are logged in as {{ user.username }}. - Log out here. +{% when Some with (user) %} +

You are logged in as {{ user.username }}. + Log out here. {% when None %} -

You are not logged in. Log in here. -{% endmatch %} +

You are not logged in. Log in here. + {% endmatch %}

Clients ({{ clients.len() }})

    - {% for client in clients %} -
  • {{ client.name }}
  • - {% endfor %} + {% for client in clients %} +
  • {{ client.name }}
  • + {% endfor %}

Users ({{ users.len() }})

{% endblock content %} diff --git a/templates/users/index.html b/templates/users/index.html index d78af34f..63cd9ec5 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -5,6 +5,12 @@

Users ({{ users.len() }})

Username Admin? + Firstname + Lastname + Email + ssh key + Last accessed at + Created at {% for user in users %} @@ -14,6 +20,19 @@

Users ({{ users.len() }})

{% else %} No {% endif%} + {{ user.firstname }} + {{ user.lastname }} + {{ user.email }} + + {% match user.ssh_key %} + {% when Some with (val) %} + Found {{ val }} + {% when None %} + Not configured + {% endmatch %} + + {{ user.last_accessed_at }} + {{ user.created_at }} {% endfor %} @@ -22,8 +41,22 @@

Users ({{ users.len() }})

+ + + + + + + + + + + + + +
{% endif %} diff --git a/templates/users/show.html b/templates/users/show.html index 05bc1429..a3558535 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -2,8 +2,60 @@ {% block content %}

{{ user.username }}

{% if user.admin %} -

This user is an admin. -{% else %} -

This is a normal user. -{% endif %} +

This user is an admin. + {% else %} +

This is a normal user. + {% endif %} + +

TODO: Add password change option (enter old and 2 times new)

+ +
+ + + + + + + + + + + + + + + + + + + +
+ + {% endblock content %} From ea30823540d5371748a3da12d32ce7f57dd1b81b Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 7 Aug 2020 01:47:03 +0200 Subject: [PATCH 03/23] last_accessed_at -> last_seen --- migrations/2019-10-30-155718_schema/up.sql | 20 ++++++------ src/models/user.rs | 38 +++++++++++----------- templates/users/index.html | 2 +- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index d80d89ca..174f5bb5 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -1,15 +1,15 @@ CREATE TABLE users ( - id SERIAL PRIMARY KEY, - username VARCHAR(255) NOT NULL UNIQUE, - hashed_password VARCHAR(255) NOT NULL, - admin BOOLEAN NOT NULL DEFAULT false, - firstname VARCHAR(255) NOT NULL, - lastname VARCHAR(255) NOT NULL, - email VARCHAR(255) NOT NULL, -- TO BE OR NOT TE UNIQUE? - ssh_key TEXT, - last_accessed_at DATETIME NOT NULL, - created_at DATETIME NOT NULL DEFAULT NOW() + id SERIAL PRIMARY KEY, + username VARCHAR(255) NOT NULL UNIQUE, + hashed_password VARCHAR(255) NOT NULL, + admin BOOLEAN NOT NULL DEFAULT false, + firstname VARCHAR(255) NOT NULL, + lastname VARCHAR(255) NOT NULL, + email VARCHAR(255) NOT NULL, -- TO BE OR NOT TE UNIQUE? + ssh_key TEXT, + last_seen DATETIME NOT NULL, + created_at DATETIME NOT NULL DEFAULT NOW() ); CREATE INDEX ix_user_username ON user (username); diff --git a/src/models/user.rs b/src/models/user.rs index ef140a81..6918f349 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -24,7 +24,7 @@ mod schema { lastname -> Varchar, email -> Varchar, ssh_key -> Nullable, - last_accessed_at -> Datetime, + last_seen -> Datetime, created_at -> Datetime, } } @@ -40,12 +40,12 @@ pub struct User { pub hashed_password: String, pub admin: bool, - pub firstname: String, - pub lastname: String, - pub email: String, - pub ssh_key: Option, - pub last_accessed_at: NaiveDateTime, - pub created_at: NaiveDateTime, + pub firstname: String, + pub lastname: String, + pub email: String, + pub ssh_key: Option, + pub last_seen: NaiveDateTime, + pub created_at: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -61,12 +61,12 @@ pub struct NewUser { #[table_name = "users"] #[derive(Serialize, Insertable, Debug, Clone)] struct NewUserHashed { - username: String, - hashed_password: String, - firstname: String, - lastname: String, - email: String, - last_accessed_at: NaiveDateTime, + username: String, + hashed_password: String, + firstname: String, + lastname: String, + email: String, + last_seen: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -103,12 +103,12 @@ impl User { pub fn create(user: NewUser, conn: &ConcreteConnection) -> Result { let user = NewUserHashed { - username: user.username, - hashed_password: hash(&user.password).ok()?, - firstname: user.firstname, - lastname: user.lastname, - email: user.email, - last_accessed_at: Utc::now().naive_utc(), + username: user.username, + hashed_password: hash(&user.password).ok()?, + firstname: user.firstname, + lastname: user.lastname, + email: user.email, + last_seen: Utc::now().naive_utc(), }; conn.transaction(|| { // Create a new user diff --git a/templates/users/index.html b/templates/users/index.html index 63cd9ec5..87471a85 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -31,7 +31,7 @@

Users ({{ users.len() }})

Not configured {% endmatch %} - {{ user.last_accessed_at }} + {{ user.last_seen }} {{ user.created_at }} {% endfor %} From 75f405af48a99db518bd2a26b5925078bf76d3f2 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 7 Aug 2020 02:23:50 +0200 Subject: [PATCH 04/23] Fix date types --- Cargo.lock | 2 +- README.md | 7 ++++--- migrations/2019-10-30-155718_schema/up.sql | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 560a7b54..8dd531d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1270,7 +1270,7 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.6.1" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ diff --git a/README.md b/README.md index 0c09ee66..73dd7490 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,10 @@ The name is open for discussion. with `cargo install diesel_cli`. 4. Create the development and testing database with - `diesel database reset --database-url "postgresql://zauth:zauth@localhost/zauth"` - and - `diesel database reset --database-url "postgresql://zauth:zauth@localhost/zauth_test"`. + ```shell script + diesel database reset --database-url "postgresql://zauth:zauth@localhost/zauth" + diesel database reset --database-url "postgresql://zauth:zauth@localhost/zauth_test" + ``` This will also run the migrations. 5. You can start the server with `cargo run`. diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 174f5bb5..1173cb8f 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -8,8 +8,8 @@ CREATE TABLE users lastname VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL, -- TO BE OR NOT TE UNIQUE? ssh_key TEXT, - last_seen DATETIME NOT NULL, - created_at DATETIME NOT NULL DEFAULT NOW() + last_seen TIMESTAMP NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE INDEX ix_user_username ON user (username); From 30a4092b3ec8d93f6dd486e6bbaa949229b2de93 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 7 Aug 2020 02:31:12 +0200 Subject: [PATCH 05/23] Fix dates in scheme --- src/models/user.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/user.rs b/src/models/user.rs index 6918f349..e268335b 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -24,9 +24,9 @@ mod schema { lastname -> Varchar, email -> Varchar, ssh_key -> Nullable, - last_seen -> Datetime, - created_at -> Datetime, - } + last_seen -> Timestamp, + created_at -> Timestamp, + } } } From 1fead5367801321abba7b8d433c642dd6999daca Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 09:55:31 +0200 Subject: [PATCH 06/23] Make email unique for user --- migrations/2019-10-30-155718_schema/up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 1173cb8f..7d785406 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -6,7 +6,7 @@ CREATE TABLE users admin BOOLEAN NOT NULL DEFAULT false, firstname VARCHAR(255) NOT NULL, lastname VARCHAR(255) NOT NULL, - email VARCHAR(255) NOT NULL, -- TO BE OR NOT TE UNIQUE? + email VARCHAR(255) NOT NULL UNIQUE, ssh_key TEXT, last_seen TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW() From f19187dcef67fca78cc7f1eba184bb36c2f16d2c Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 10:14:08 +0200 Subject: [PATCH 07/23] Add column for upcoming password change --- templates/users/show.html | 94 +++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/templates/users/show.html b/templates/users/show.html index a3558535..a61f0061 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -9,53 +9,71 @@

{{ user.username }}

TODO: Add password change option (enter old and 2 times new)

-
- - +
- - - - - +
+
+

+ Update profile info +

- - + + + - - + + - - Firstname + + + + + + + + + + - - - + + + +
+
+

+ Set new password +

+

Coming soon!

+
+
+
+ {% endblock content %} From 1a4a094e4ff19435a3cfbdf15b255b675dd562ac Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 11:35:28 +0200 Subject: [PATCH 08/23] Update newUser structs in tests --- src/models/user.rs | 4 +++- tests/common/mod.rs | 8 ++++++++ tests/users.rs | 34 +++++++++++++++++++++++++++------- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/models/user.rs b/src/models/user.rs index e268335b..b76f2d9e 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -66,6 +66,7 @@ struct NewUserHashed { firstname: String, lastname: String, email: String, + ssh_key: Option, last_seen: NaiveDateTime, } @@ -108,6 +109,7 @@ impl User { firstname: user.firstname, lastname: user.lastname, email: user.email, + ssh_key: user.ssh_key, last_seen: Utc::now().naive_utc(), }; conn.transaction(|| { @@ -126,7 +128,7 @@ impl User { self.username = username; } if let Some(password) = change.password { - self.hashed_password = hash(&password)?; + self.hashed_password = hash(&password).ok()?; } if let Some(firstname) = change.firstname { self.firstname = firstname; diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 2192a3ba..ee5e0ac8 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -71,6 +71,10 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { NewUser { username: String::from("user"), password: String::from("user"), + firstname: String::from("user"), + lastname: String::from("user"), + email: String::from("user"), + ssh_key: Some(String::from("user")), }, &db, ) @@ -96,6 +100,10 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { NewUser { username: String::from("admin"), password: String::from("admin"), + firstname: String::from("admin"), + lastname: String::from("admin"), + email: String::from("admin"), + ssh_key: Some(String::from("admin")), }, &db, ) diff --git a/tests/users.rs b/tests/users.rs index c8dd4bcd..2ed21342 100644 --- a/tests/users.rs +++ b/tests/users.rs @@ -45,7 +45,11 @@ fn show_user_as_user() { let other = User::create( NewUser { username: String::from("somebody"), - password: String::from("else"), + password: String::from("once"), + firstname: String::from("told"), + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")) }, &db, ) @@ -79,7 +83,11 @@ fn show_user_as_admin() { let other = User::create( NewUser { username: String::from("somebody"), - password: String::from("else"), + password: String::from("once"), + firstname: String::from("told"), + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")) }, &db, ) @@ -128,7 +136,11 @@ fn update_self() { let other = User::create( NewUser { username: String::from("somebody"), - password: String::from("else"), + password: String::from("once"), + firstname: String::from("told"), + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")) }, &db, ) @@ -179,8 +191,12 @@ fn make_admin() { common::as_admin(|http_client, db, _admin| { let other = User::create( NewUser { - username: String::from("padawan"), - password: String::from(""), + username: String::from("somebody"), + password: String::from("once"), + firstname: String::from("told"), + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")) }, &db, ) @@ -210,8 +226,12 @@ fn try_make_admin() { common::as_user(|http_client, db, _user| { let other = User::create( NewUser { - username: String::from("acccomplice"), - password: String::from("not_an_admin"), + username: String::from("somebody"), + password: String::from("once"), + firstname: String::from("told"), + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")) }, &db, ) From 4d7b5989e7d87853d6c9081099bbcaadfc9dbe9f Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 11:40:32 +0200 Subject: [PATCH 09/23] Fix more user forms in the tests --- tests/oauth.rs | 4 ++++ tests/users.rs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/oauth.rs b/tests/oauth.rs index d304f590..ec824f40 100644 --- a/tests/oauth.rs +++ b/tests/oauth.rs @@ -40,6 +40,10 @@ fn normal_flow() { NewUser { username: String::from(user_username), password: String::from(user_password), + firstname: String::from("abc"), + lastname: String::from("def"), + email: String::from("ghi@jkl.mno"), + ssh_key: Some(String::from("pqrstuvwxyz")) }, &db, ) diff --git a/tests/users.rs b/tests/users.rs index 2ed21342..79adb8e5 100644 --- a/tests/users.rs +++ b/tests/users.rs @@ -261,7 +261,7 @@ fn create_user_form() { .post("/users") .header(ContentType::Form) .header(Accept::JSON) - .body("username=testuser&password=testpassword") + .body("username=testuser&password=testpassword&firstname=abc&lastname=def&email=hij@klm.op&ssh_key=qrs") .dispatch(); assert_eq!(response.status(), Status::Ok); @@ -283,7 +283,7 @@ fn create_user_json() { .header(ContentType::JSON) .header(Accept::JSON) .body( - "{\"username\": \"testuser\", \"password\": \"testpassword\"}", + "{\"username\": \"testuser\", \"password\": \"testpassword\", \"firstname\": \"abc\", \"lastname\": \"def\", \"email\": \"hij@klm.op\", \"ssh_key\": \"qrs\"}", ) .dispatch(); From 6629de8fb007ffe0e6e529c6e4e7ca036d80a3db Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 13:46:17 +0200 Subject: [PATCH 10/23] convert put to urlencoded form instead of formdata --- templates/users/show.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/users/show.html b/templates/users/show.html index a61f0061..9463afab 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -55,10 +55,11 @@

function putForm(url, formSelector) { const formData = new FormData(document.querySelector(formSelector)) + const urlEncoded = new URLSearchParams(formData) fetch(url, { method: 'PUT', // 'GET', 'PUT', 'DELETE', etc. - body: formData // a FormData will automatically set the 'Content-Type' + body: urlEncoded, // this will automatically set the 'Content-Type' }) .then(response => response.json()) .catch(error => console.error(error)) From 9e45ba77a39365e46e777e9079a1fec0f0f611a4 Mon Sep 17 00:00:00 2001 From: Maxime <12089026+mcbloch@users.noreply.github.com> Date: Tue, 11 Aug 2020 23:24:24 +0200 Subject: [PATCH 11/23] Make ssh uppercase in html Co-authored-by: Rien --- templates/users/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/users/index.html b/templates/users/index.html index 87471a85..37036dca 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -8,7 +8,7 @@

Users ({{ users.len() }})

Firstname Lastname Email - ssh key + SSH key Last accessed at Created at From 69ec52825a24de40907fcc78961504882a0864d3 Mon Sep 17 00:00:00 2001 From: Maxime <12089026+mcbloch@users.noreply.github.com> Date: Tue, 11 Aug 2020 23:27:29 +0200 Subject: [PATCH 12/23] Change show name of the last_seen field. Co-authored-by: Rien --- templates/users/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/users/index.html b/templates/users/index.html index 37036dca..1755f84b 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -9,7 +9,7 @@

Users ({{ users.len() }})

Lastname Email SSH key - Last accessed at + Last login Created at {% for user in users %} From 9da527e504c103e19f756fb9cb6a43f73e2605ab Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 23:35:00 +0200 Subject: [PATCH 13/23] Add created at field to client --- migrations/2019-10-30-155718_schema/up.sql | 3 ++- src/models/client.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 7d785406..92814fe3 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -22,5 +22,6 @@ CREATE TABLE clients name VARCHAR(255) NOT NULL UNIQUE, secret VARCHAR(255) NOT NULL, needs_grant BOOLEAN NOT NULL DEFAULT false, - redirect_uri_list TEXT NOT NULL DEFAULT '' + redirect_uri_list TEXT NOT NULL DEFAULT '', + created_at TIMESTAMP NOT NULL DEFAULT NOW() ); diff --git a/src/models/client.rs b/src/models/client.rs index 711dfb82..5fea8a69 100644 --- a/src/models/client.rs +++ b/src/models/client.rs @@ -17,6 +17,7 @@ mod schema { secret -> Text, needs_grant -> Bool, redirect_uri_list -> Text, + created_at -> Timestamp, } } } From 753a385f2b1f5e9c2a726d6345168620423d63e9 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 23:42:21 +0200 Subject: [PATCH 14/23] Add created_at struct field to client, remove 'Found' debug string from html --- src/models/client.rs | 5 +++++ templates/users/index.html | 2 +- templates/users/show.html | 8 ++------ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/models/client.rs b/src/models/client.rs index 5fea8a69..779896c7 100644 --- a/src/models/client.rs +++ b/src/models/client.rs @@ -7,6 +7,10 @@ use crate::ConcreteConnection; use self::schema::clients; +use crate::ConcreteConnection; + +use chrono::{NaiveDateTime, Utc}; + const SECRET_LENGTH: usize = 64; mod schema { @@ -29,6 +33,7 @@ pub struct Client { pub secret: String, pub needs_grant: bool, pub redirect_uri_list: String, + pub created_at: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] diff --git a/templates/users/index.html b/templates/users/index.html index 1755f84b..89a2ea4d 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -26,7 +26,7 @@

Users ({{ users.len() }})

{% match user.ssh_key %} {% when Some with (val) %} - Found {{ val }} + {{ val }} {% when None %} Not configured {% endmatch %} diff --git a/templates/users/show.html b/templates/users/show.html index 9463afab..63594e8f 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -34,12 +34,8 @@

- + From 59154382eec9ca075529f0d7488fe031d97c2700 Mon Sep 17 00:00:00 2001 From: Maxime <12089026+mcbloch@users.noreply.github.com> Date: Tue, 11 Aug 2020 23:49:32 +0200 Subject: [PATCH 15/23] firstname -> first_name Co-authored-by: Rien --- migrations/2019-10-30-155718_schema/up.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 92814fe3..29dc0902 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -4,8 +4,8 @@ CREATE TABLE users username VARCHAR(255) NOT NULL UNIQUE, hashed_password VARCHAR(255) NOT NULL, admin BOOLEAN NOT NULL DEFAULT false, - firstname VARCHAR(255) NOT NULL, - lastname VARCHAR(255) NOT NULL, + first_name VARCHAR(255) NOT NULL, + last_name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, ssh_key TEXT, last_seen TIMESTAMP NOT NULL, From c1206b5dda107d67195ea9adc2d73f7f61767089 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Tue, 11 Aug 2020 23:51:12 +0200 Subject: [PATCH 16/23] Run cargo fmt on the project. --- tests/common/mod.rs | 20 +++++++-------- tests/oauth.rs | 10 ++++---- tests/users.rs | 59 ++++++++++++++++++++++++--------------------- 3 files changed, 47 insertions(+), 42 deletions(-) diff --git a/tests/common/mod.rs b/tests/common/mod.rs index ee5e0ac8..1b0f5e00 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -69,12 +69,12 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { as_visitor(|client, db| { let user = User::create( NewUser { - username: String::from("user"), - password: String::from("user"), + username: String::from("user"), + password: String::from("user"), firstname: String::from("user"), - lastname: String::from("user"), - email: String::from("user"), - ssh_key: Some(String::from("user")), + lastname: String::from("user"), + email: String::from("user"), + ssh_key: Some(String::from("user")), }, &db, ) @@ -98,12 +98,12 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { as_visitor(|client, db| { let mut user = User::create( NewUser { - username: String::from("admin"), - password: String::from("admin"), + username: String::from("admin"), + password: String::from("admin"), firstname: String::from("admin"), - lastname: String::from("admin"), - email: String::from("admin"), - ssh_key: Some(String::from("admin")), + lastname: String::from("admin"), + email: String::from("admin"), + ssh_key: Some(String::from("admin")), }, &db, ) diff --git a/tests/oauth.rs b/tests/oauth.rs index ec824f40..156a5e3e 100644 --- a/tests/oauth.rs +++ b/tests/oauth.rs @@ -38,12 +38,12 @@ fn normal_flow() { let user = User::create( NewUser { - username: String::from(user_username), - password: String::from(user_password), + username: String::from(user_username), + password: String::from(user_password), firstname: String::from("abc"), - lastname: String::from("def"), - email: String::from("ghi@jkl.mno"), - ssh_key: Some(String::from("pqrstuvwxyz")) + lastname: String::from("def"), + email: String::from("ghi@jkl.mno"), + ssh_key: Some(String::from("pqrstuvwxyz")), }, &db, ) diff --git a/tests/users.rs b/tests/users.rs index 79adb8e5..7048ad07 100644 --- a/tests/users.rs +++ b/tests/users.rs @@ -44,12 +44,12 @@ fn show_user_as_user() { common::as_user(|http_client, db, user| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), + username: String::from("somebody"), + password: String::from("once"), firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")) + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -82,12 +82,12 @@ fn show_user_as_admin() { common::as_admin(|http_client, db, admin| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), + username: String::from("somebody"), + password: String::from("once"), firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")) + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -135,12 +135,12 @@ fn update_self() { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), + username: String::from("somebody"), + password: String::from("once"), firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")) + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -191,12 +191,12 @@ fn make_admin() { common::as_admin(|http_client, db, _admin| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), + username: String::from("somebody"), + password: String::from("once"), firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")) + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -226,12 +226,12 @@ fn try_make_admin() { common::as_user(|http_client, db, _user| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), + username: String::from("somebody"), + password: String::from("once"), firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")) + lastname: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -261,7 +261,10 @@ fn create_user_form() { .post("/users") .header(ContentType::Form) .header(Accept::JSON) - .body("username=testuser&password=testpassword&firstname=abc&lastname=def&email=hij@klm.op&ssh_key=qrs") + .body( + "username=testuser&password=testpassword&firstname=abc&\ + lastname=def&email=hij@klm.op&ssh_key=qrs", + ) .dispatch(); assert_eq!(response.status(), Status::Ok); @@ -283,7 +286,9 @@ fn create_user_json() { .header(ContentType::JSON) .header(Accept::JSON) .body( - "{\"username\": \"testuser\", \"password\": \"testpassword\", \"firstname\": \"abc\", \"lastname\": \"def\", \"email\": \"hij@klm.op\", \"ssh_key\": \"qrs\"}", + "{\"username\": \"testuser\", \"password\": \"testpassword\", \ + \"firstname\": \"abc\", \"lastname\": \"def\", \"email\": \ + \"hij@klm.op\", \"ssh_key\": \"qrs\"}", ) .dispatch(); From ea09e671b4c3bafcd23f57d34c5e61b77e1c4c8b Mon Sep 17 00:00:00 2001 From: mcbloch Date: Wed, 12 Aug 2020 00:00:40 +0200 Subject: [PATCH 17/23] Change firstname -> first_name everywhere --- src/lib.rs | 24 +++++++------- src/models/user.rs | 48 +++++++++++++-------------- templates/users/index.html | 16 ++++----- templates/users/show.html | 8 ++--- tests/common/mod.rs | 24 +++++++------- tests/oauth.rs | 12 +++---- tests/users.rs | 66 +++++++++++++++++++------------------- 7 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fb09b307..12f74566 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,24 +112,24 @@ fn assemble(rocket: Rocket) -> Rocket { .or_else(|_e| { User::create( NewUser { - username: String::from("admin"), - password: String::from(&pw), - firstname: String::from(""), - lastname: String::from(""), - email: String::from(""), - ssh_key: None, + username: String::from("admin"), + password: String::from(&pw), + first_name: String::from(""), + last_name: String::from(""), + email: String::from(""), + ssh_key: None, }, &conn, ) }) .and_then(|mut user| { user.change_with(UserChange { - username: None, - password: Some(pw), - firstname: None, - lastname: None, - email: None, - ssh_key: None, + username: None, + password: Some(pw), + first_name: None, + last_name: None, + email: None, + ssh_key: None, })?; user.admin = true; user.update(&conn) diff --git a/src/models/user.rs b/src/models/user.rs index b76f2d9e..7a1d5d24 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -20,8 +20,8 @@ mod schema { username -> Varchar, hashed_password -> Varchar, admin -> Bool, - firstname -> Varchar, - lastname -> Varchar, + first_name -> Varchar, + last_name -> Varchar, email -> Varchar, ssh_key -> Nullable, last_seen -> Timestamp, @@ -40,8 +40,8 @@ pub struct User { pub hashed_password: String, pub admin: bool, - pub firstname: String, - pub lastname: String, + pub first_name: String, + pub last_name: String, pub email: String, pub ssh_key: Option, pub last_seen: NaiveDateTime, @@ -50,12 +50,12 @@ pub struct User { #[derive(FromForm, Deserialize, Debug, Clone)] pub struct NewUser { - pub username: String, - pub password: String, - pub firstname: String, - pub lastname: String, - pub email: String, - pub ssh_key: Option, + pub username: String, + pub password: String, + pub first_name: String, + pub last_name: String, + pub email: String, + pub ssh_key: Option, } #[table_name = "users"] @@ -63,8 +63,8 @@ pub struct NewUser { struct NewUserHashed { username: String, hashed_password: String, - firstname: String, - lastname: String, + first_name: String, + last_name: String, email: String, ssh_key: Option, last_seen: NaiveDateTime, @@ -72,12 +72,12 @@ struct NewUserHashed { #[derive(FromForm, Deserialize, Debug, Clone)] pub struct UserChange { - pub username: Option, - pub password: Option, - pub firstname: Option, - pub lastname: Option, - pub email: Option, - pub ssh_key: Option, + pub username: Option, + pub password: Option, + pub first_name: Option, + pub last_name: Option, + pub email: Option, + pub ssh_key: Option, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -106,8 +106,8 @@ impl User { let user = NewUserHashed { username: user.username, hashed_password: hash(&user.password).ok()?, - firstname: user.firstname, - lastname: user.lastname, + first_name: user.first_name, + last_name: user.last_name, email: user.email, ssh_key: user.ssh_key, last_seen: Utc::now().naive_utc(), @@ -130,11 +130,11 @@ impl User { if let Some(password) = change.password { self.hashed_password = hash(&password).ok()?; } - if let Some(firstname) = change.firstname { - self.firstname = firstname; + if let Some(first_name) = change.first_name { + self.first_name = first_name; } - if let Some(lastname) = change.lastname { - self.lastname = lastname; + if let Some(last_name) = change.last_name { + self.last_name = last_name; } if let Some(email) = change.email { self.email = email; diff --git a/templates/users/index.html b/templates/users/index.html index 89a2ea4d..b88d5af6 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -5,8 +5,8 @@

Users ({{ users.len() }})

Username Admin? - Firstname - Lastname + First Name + Last Name Email SSH key Last login @@ -20,8 +20,8 @@

Users ({{ users.len() }})

{% else %} No {% endif%} - {{ user.firstname }} - {{ user.lastname }} + {{ user.first_name }} + {{ user.last_name }} {{ user.email }} {% match user.ssh_key %} @@ -45,11 +45,11 @@

Users ({{ users.len() }})

- - + + - - + + diff --git a/templates/users/show.html b/templates/users/show.html index 63594e8f..ec315af4 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -24,11 +24,11 @@

- - + + - - + + diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 1b0f5e00..3f06fda7 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -69,12 +69,12 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { as_visitor(|client, db| { let user = User::create( NewUser { - username: String::from("user"), - password: String::from("user"), - firstname: String::from("user"), - lastname: String::from("user"), - email: String::from("user"), - ssh_key: Some(String::from("user")), + username: String::from("user"), + password: String::from("user"), + first_name: String::from("user"), + last_name: String::from("user"), + email: String::from("user"), + ssh_key: Some(String::from("user")), }, &db, ) @@ -98,12 +98,12 @@ where F: FnOnce(HttpClient, DbConn, User) -> () { as_visitor(|client, db| { let mut user = User::create( NewUser { - username: String::from("admin"), - password: String::from("admin"), - firstname: String::from("admin"), - lastname: String::from("admin"), - email: String::from("admin"), - ssh_key: Some(String::from("admin")), + username: String::from("admin"), + password: String::from("admin"), + first_name: String::from("admin"), + last_name: String::from("admin"), + email: String::from("admin"), + ssh_key: Some(String::from("admin")), }, &db, ) diff --git a/tests/oauth.rs b/tests/oauth.rs index 156a5e3e..7fc75e02 100644 --- a/tests/oauth.rs +++ b/tests/oauth.rs @@ -38,12 +38,12 @@ fn normal_flow() { let user = User::create( NewUser { - username: String::from(user_username), - password: String::from(user_password), - firstname: String::from("abc"), - lastname: String::from("def"), - email: String::from("ghi@jkl.mno"), - ssh_key: Some(String::from("pqrstuvwxyz")), + username: String::from(user_username), + password: String::from(user_password), + first_name: String::from("abc"), + last_name: String::from("def"), + email: String::from("ghi@jkl.mno"), + ssh_key: Some(String::from("pqrstuvwxyz")), }, &db, ) diff --git a/tests/users.rs b/tests/users.rs index 7048ad07..444d97fc 100644 --- a/tests/users.rs +++ b/tests/users.rs @@ -44,12 +44,12 @@ fn show_user_as_user() { common::as_user(|http_client, db, user| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), - firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")), + username: String::from("somebody"), + password: String::from("once"), + first_name: String::from("told"), + last_name: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -82,12 +82,12 @@ fn show_user_as_admin() { common::as_admin(|http_client, db, admin| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), - firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")), + username: String::from("somebody"), + password: String::from("once"), + first_name: String::from("told"), + last_name: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -135,12 +135,12 @@ fn update_self() { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), - firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")), + username: String::from("somebody"), + password: String::from("once"), + first_name: String::from("told"), + last_name: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -191,12 +191,12 @@ fn make_admin() { common::as_admin(|http_client, db, _admin| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), - firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")), + username: String::from("somebody"), + password: String::from("once"), + first_name: String::from("told"), + last_name: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -226,12 +226,12 @@ fn try_make_admin() { common::as_user(|http_client, db, _user| { let other = User::create( NewUser { - username: String::from("somebody"), - password: String::from("once"), - firstname: String::from("told"), - lastname: String::from("me"), - email: String::from("zeus"), - ssh_key: Some(String::from("would be forever")), + username: String::from("somebody"), + password: String::from("once"), + first_name: String::from("told"), + last_name: String::from("me"), + email: String::from("zeus"), + ssh_key: Some(String::from("would be forever")), }, &db, ) @@ -262,8 +262,8 @@ fn create_user_form() { .header(ContentType::Form) .header(Accept::JSON) .body( - "username=testuser&password=testpassword&firstname=abc&\ - lastname=def&email=hij@klm.op&ssh_key=qrs", + "username=testuser&password=testpassword&first_name=abc&\ + last_name=def&email=hij@klm.op&ssh_key=qrs", ) .dispatch(); @@ -287,7 +287,7 @@ fn create_user_json() { .header(Accept::JSON) .body( "{\"username\": \"testuser\", \"password\": \"testpassword\", \ - \"firstname\": \"abc\", \"lastname\": \"def\", \"email\": \ + \"first_name\": \"abc\", \"last_name\": \"def\", \"email\": \ \"hij@klm.op\", \"ssh_key\": \"qrs\"}", ) .dispatch(); From 3a0630ad2acb51d53ab1eee1ba097473196e63ae Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 18:10:28 +0200 Subject: [PATCH 18/23] Push serde dep back up --- Cargo.lock | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 8dd531d7..31896b34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,6 +589,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.5.1" @@ -1270,7 +1280,7 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" dependencies = [ @@ -1545,6 +1555,16 @@ dependencies = [ "percent-encoding 2.1.0", ] +[[package]] +name = "url" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "urlencoding" version = "1.1.1" From 13ea55f7839b9222145d07ff8d43c68fceabda2a Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 18:24:24 +0200 Subject: [PATCH 19/23] Change last_seen to last_login --- migrations/2019-10-30-155718_schema/up.sql | 2 +- src/models/user.rs | 8 ++++---- templates/users/index.html | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 29dc0902..4bc8a321 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -8,7 +8,7 @@ CREATE TABLE users last_name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, ssh_key TEXT, - last_seen TIMESTAMP NOT NULL, + last_login TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); diff --git a/src/models/user.rs b/src/models/user.rs index 7a1d5d24..9781541a 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -24,7 +24,7 @@ mod schema { last_name -> Varchar, email -> Varchar, ssh_key -> Nullable, - last_seen -> Timestamp, + last_login -> Timestamp, created_at -> Timestamp, } } @@ -44,7 +44,7 @@ pub struct User { pub last_name: String, pub email: String, pub ssh_key: Option, - pub last_seen: NaiveDateTime, + pub last_login: NaiveDateTime, pub created_at: NaiveDateTime, } @@ -67,7 +67,7 @@ struct NewUserHashed { last_name: String, email: String, ssh_key: Option, - last_seen: NaiveDateTime, + last_login: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -110,7 +110,7 @@ impl User { last_name: user.last_name, email: user.email, ssh_key: user.ssh_key, - last_seen: Utc::now().naive_utc(), + last_login: Utc::now().naive_utc(), }; conn.transaction(|| { // Create a new user diff --git a/templates/users/index.html b/templates/users/index.html index b88d5af6..b8fe2f1f 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -31,7 +31,7 @@

Users ({{ users.len() }})

Not configured {% endmatch %} - {{ user.last_seen }} + {{ user.last_login }} {{ user.created_at }} {% endfor %} From 953b1b3ea99be804be207d480babe00d1280a08f Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 18:41:23 +0200 Subject: [PATCH 20/23] Run rustfmt --- src/models/user.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/user.rs b/src/models/user.rs index 9781541a..6824cbce 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -44,7 +44,7 @@ pub struct User { pub last_name: String, pub email: String, pub ssh_key: Option, - pub last_login: NaiveDateTime, + pub last_login: NaiveDateTime, pub created_at: NaiveDateTime, } @@ -67,7 +67,7 @@ struct NewUserHashed { last_name: String, email: String, ssh_key: Option, - last_login: NaiveDateTime, + last_login: NaiveDateTime, } #[derive(FromForm, Deserialize, Debug, Clone)] @@ -110,7 +110,7 @@ impl User { last_name: user.last_name, email: user.email, ssh_key: user.ssh_key, - last_login: Utc::now().naive_utc(), + last_login: Utc::now().naive_utc(), }; conn.transaction(|| { // Create a new user From d0999bb1cbd4f72337f3e8e39f2882689e1b3be4 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 20:29:42 +0200 Subject: [PATCH 21/23] Fix merge result --- Cargo.lock | 58 +++++++--------------- migrations/2019-10-30-155718_schema/up.sql | 4 +- src/models/client.rs | 2 - src/models/user.rs | 10 ++-- templates/users/show.html | 2 - 5 files changed, 26 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31896b34..b1d6ed39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -123,9 +123,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "base64" @@ -238,9 +238,9 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "chrono" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c74d84029116787153e02106bf53e66828452a4b325cc8652b788b5967c0a0b6" +checksum = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b" dependencies = [ "num-integer", "num-traits", @@ -339,7 +339,7 @@ checksum = "3e2de9deab977a153492a1468d1b1c0662c1cf39e5ea87d0c060ecd59ef18d8c" dependencies = [ "bitflags", "byteorder", - "chrono 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono", "diesel_derives", "pq-sys", "r2d2", @@ -589,16 +589,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "idna" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "indexmap" version = "1.5.1" @@ -674,15 +664,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" +checksum = "755456fae044e6fa1ebbbd1b3e902ae19e73097ed4ed87bb79934a867c007bc3" [[package]] name = "lock_api" @@ -981,9 +971,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] name = "pq-sys" @@ -1249,18 +1239,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3" +checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e" +checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48" dependencies = [ "proc-macro2 1.0.19", "quote 1.0.7", @@ -1336,9 +1326,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3757cb9d89161a2f24e1cf78efa0c1fcff485d18e3f55e0aa3480824ddaa0f3f" +checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252" [[package]] name = "state" @@ -1435,9 +1425,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53953d2d3a5ad81d9f844a32f14ebb121f50b650cd59d0ee2a07cf13c617efed" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" [[package]] name = "toml" @@ -1555,16 +1545,6 @@ dependencies = [ "percent-encoding 2.1.0", ] -[[package]] -name = "url" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "urlencoding" version = "1.1.1" diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 4bc8a321..3dbcd979 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -12,8 +12,8 @@ CREATE TABLE users created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -CREATE INDEX ix_user_username ON user (username); -CREATE INDEX ix_user_email ON user (email); +CREATE INDEX ix_users_username ON users (username); +CREATE INDEX ix_users_email ON users (email); CREATE TABLE clients diff --git a/src/models/client.rs b/src/models/client.rs index 779896c7..6138594d 100644 --- a/src/models/client.rs +++ b/src/models/client.rs @@ -7,8 +7,6 @@ use crate::ConcreteConnection; use self::schema::clients; -use crate::ConcreteConnection; - use chrono::{NaiveDateTime, Utc}; const SECRET_LENGTH: usize = 64; diff --git a/src/models/user.rs b/src/models/user.rs index 6824cbce..28e95f6d 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -105,7 +105,7 @@ impl User { pub fn create(user: NewUser, conn: &ConcreteConnection) -> Result { let user = NewUserHashed { username: user.username, - hashed_password: hash(&user.password).ok()?, + hashed_password: hash(&user.password)?, first_name: user.first_name, last_name: user.last_name, email: user.email, @@ -114,13 +114,13 @@ impl User { }; conn.transaction(|| { // Create a new user - diesel::insert_into(user::table) + diesel::insert_into(users::table) .values(&user) .execute(conn)?; // Fetch the last created user - users.order(user::id.desc()).first(conn) + let user = users::table.order(users::id.desc()).first(conn)?; + Ok(user) }) - .ok() } pub fn change_with(&mut self, change: UserChange) -> Result<()> { @@ -128,7 +128,7 @@ impl User { self.username = username; } if let Some(password) = change.password { - self.hashed_password = hash(&password).ok()?; + self.hashed_password = hash(&password)?; } if let Some(first_name) = change.first_name { self.first_name = first_name; diff --git a/templates/users/show.html b/templates/users/show.html index ec315af4..4dd3a315 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -7,8 +7,6 @@

{{ user.username }}

This is a normal user. {% endif %} -

TODO: Add password change option (enter old and 2 times new)

-
From 723e1a937fdd41d23c586946850d04437f40f0e0 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 21:30:28 +0200 Subject: [PATCH 22/23] Add userstate to user model --- Cargo.lock | 28 ++++++++++++++++++++++ Cargo.toml | 1 + diesel.toml | 2 ++ migrations/2019-10-30-155718_schema/up.sql | 3 +++ src/controllers/sessions_controller.rs | 2 +- src/models/user.rs | 24 +++++++++++++++++++ templates/users/index.html | 2 ++ 7 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b1d6ed39..464b85dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,18 @@ dependencies = [ "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.19", + "quote 1.0.7", + "syn 1.0.38", +] + [[package]] name = "diesel_derives" version = "1.4.1" @@ -497,6 +509,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.1.15" @@ -1501,6 +1522,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -1654,6 +1681,7 @@ dependencies = [ "bincode", "chrono", "diesel", + "diesel-derive-enum", "diesel_migrations", "lazy_static", "maplit", diff --git a/Cargo.toml b/Cargo.toml index db96ff57..c0104c32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ serde_json = "1.0" serde_derive = "1.0" serde_urlencoded = "0.6" diesel = { version = "1.4", features = ["postgres", "r2d2", "chrono"] } +diesel-derive-enum = { version = "1", features = ["postgres"] } diesel_migrations = "1.4" tempfile = "3.1" maplit = "1.0" diff --git a/diesel.toml b/diesel.toml index 9bb0fcf4..8c6d6528 100644 --- a/diesel.toml +++ b/diesel.toml @@ -2,3 +2,5 @@ # see diesel.rs/guides/configuring-diesel-cli [print_schema] +file = "src/schema.rs" +import_types = ["diesel::sql_types::*", "crate::user_state::*"] # <- note the extra import diff --git a/migrations/2019-10-30-155718_schema/up.sql b/migrations/2019-10-30-155718_schema/up.sql index 3dbcd979..6214452e 100644 --- a/migrations/2019-10-30-155718_schema/up.sql +++ b/migrations/2019-10-30-155718_schema/up.sql @@ -1,3 +1,5 @@ +CREATE TYPE user_state AS ENUM ('pending', 'active', 'disabled'); + CREATE TABLE users ( id SERIAL PRIMARY KEY, @@ -8,6 +10,7 @@ CREATE TABLE users last_name VARCHAR(255) NOT NULL, email VARCHAR(255) NOT NULL UNIQUE, ssh_key TEXT, + state user_state NOT NULL DEFAULT 'pending', last_login TIMESTAMP NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW() ); diff --git a/src/controllers/sessions_controller.rs b/src/controllers/sessions_controller.rs index 7ea202dc..4bc4cb8a 100644 --- a/src/controllers/sessions_controller.rs +++ b/src/controllers/sessions_controller.rs @@ -47,7 +47,7 @@ pub fn create_session( Ok(Either::Right(template! { "session/login.html"; state: String = form.state.unwrap(), - error: Option = Some(String::from("Usernae or password incorrect")), + error: Option = Some(String::from("Username or password incorrect")), })) } } diff --git a/src/models/user.rs b/src/models/user.rs index 28e95f6d..a03053c5 100644 --- a/src/models/user.rs +++ b/src/models/user.rs @@ -2,6 +2,8 @@ use self::schema::users; use crate::errors::{Result, ZauthError}; use crate::ConcreteConnection; use diesel::{self, prelude::*}; +use diesel_derive_enum::DbEnum; +use std::fmt; use chrono::{NaiveDateTime, Utc}; use pwhash::bcrypt::{self, BcryptSetup}; @@ -13,8 +15,28 @@ const BCRYPT_SETUP: BcryptSetup = BcryptSetup { cost: Some(DEFAULT_COST), }; +#[derive(DbEnum, Debug, Serialize, Clone)] +pub enum UserState { + pending, + active, + disabled, +} + +impl fmt::Display for UserState { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + UserState::pending => write!(f, "Pending"), + UserState::active => write!(f, "Active"), + UserState::disabled => write!(f, "Disabled"), + } + } +} + mod schema { table! { + use diesel::sql_types::*; + use crate::models::user::UserStateMapping; + users { id -> Integer, username -> Varchar, @@ -24,6 +46,7 @@ mod schema { last_name -> Varchar, email -> Varchar, ssh_key -> Nullable, + state -> UserStateMapping, last_login -> Timestamp, created_at -> Timestamp, } @@ -44,6 +67,7 @@ pub struct User { pub last_name: String, pub email: String, pub ssh_key: Option, + pub state: UserState, pub last_login: NaiveDateTime, pub created_at: NaiveDateTime, } diff --git a/templates/users/index.html b/templates/users/index.html index b8fe2f1f..b449d3d8 100644 --- a/templates/users/index.html +++ b/templates/users/index.html @@ -9,6 +9,7 @@

Users ({{ users.len() }})

Last Name Email SSH key + State Last login Created at @@ -31,6 +32,7 @@

Users ({{ users.len() }})

Not configured {% endmatch %} + {{ user.state }} {{ user.last_login }} {{ user.created_at }} From 5e8b2c644021ebe87b516913e3e3625fe093c968 Mon Sep 17 00:00:00 2001 From: mcbloch Date: Fri, 21 Aug 2020 21:42:35 +0200 Subject: [PATCH 23/23] Use hidden _method field instead of js --- templates/users/show.html | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/templates/users/show.html b/templates/users/show.html index 4dd3a315..0341b35a 100644 --- a/templates/users/show.html +++ b/templates/users/show.html @@ -15,7 +15,9 @@

Update profile info

-
+ + + @@ -37,29 +39,6 @@

-