summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDessalines <tyhou13@gmx.com>2019-03-22 18:42:57 -0700
committerDessalines <tyhou13@gmx.com>2019-03-22 18:42:57 -0700
commite570c70701e1c66dad12bef76821f6d94c717a02 (patch)
tree070d5ba322226acd5fe0d0a7757cb936462ab2ff
parent816aa0b15f3766e340d8722f03e8b3a7633ab6fb (diff)
Adding login and Register
- Login and Register mostly working. - Starting to work on creating communities.
-rw-r--r--README.md2
-rw-r--r--server/Cargo.lock17
-rw-r--r--server/Cargo.toml2
-rw-r--r--server/migrations/2019-02-26-002946_create_user/up.sql4
-rw-r--r--server/migrations/2019-02-27-170003_create_community/up.sql2
-rw-r--r--server/src/actions/comment.rs84
-rw-r--r--server/src/actions/community.rs97
-rw-r--r--server/src/actions/post.rs68
-rw-r--r--server/src/actions/user.rs102
-rw-r--r--server/src/bin/main.rs63
-rw-r--r--server/src/lib.rs44
-rw-r--r--server/src/websocket_server/server.rs162
-rw-r--r--ui/package.json6
-rw-r--r--ui/src/components/create-community.tsx90
-rw-r--r--ui/src/components/create-post.tsx57
-rw-r--r--ui/src/components/login.tsx57
-rw-r--r--ui/src/components/navbar.tsx54
-rw-r--r--ui/src/index.tsx7
-rw-r--r--ui/src/interfaces.ts24
-rw-r--r--ui/src/main.css5
-rw-r--r--ui/src/services.ts57
-rw-r--r--ui/src/services/UserService.ts51
-rw-r--r--ui/src/services/WebSocketService.ts37
-rw-r--r--ui/src/services/index.ts2
-rw-r--r--ui/src/utils.ts7
-rw-r--r--ui/yarn.lock24
26 files changed, 825 insertions, 300 deletions
diff --git a/README.md b/README.md
index b3f8d11b..ce8672e6 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,8 @@ We have a twitter alternative (mastodon), a facebook alternative (friendica), so
- [Recursive query for adjacency list for nested comments](https://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way-to-parse-a-flat-table-into-a-tree/192462#192462)
- https://github.com/sparksuite/simplemde-markdown-editor
- [Sticky Sidebar](https://stackoverflow.com/questions/38382043/how-to-use-css-position-sticky-to-keep-a-sidebar-visible-with-bootstrap-4/49111934)
+- [RXJS websocket](https://stackoverflow.com/questions/44060315/reconnecting-a-websocket-in-angular-and-rxjs/44067972#44067972)
+- [Rust JWT](https://github.com/Keats/jsonwebtoken)
## TODOs
- Endpoints
diff --git a/server/Cargo.lock b/server/Cargo.lock
index b4557d00..21594ccf 100644
--- a/server/Cargo.lock
+++ b/server/Cargo.lock
@@ -704,6 +704,20 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "jsonwebtoken"
+version = "5.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
+ "untrusted 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1309,7 +1323,9 @@ dependencies = [
"dotenv 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)",
"strum 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1977,6 +1993,7 @@ dependencies = [
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc"
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
+"checksum jsonwebtoken 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8d438ea707d465c230305963b67f8357a1d56fcfad9434797d7cb1c46c2e41df"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a"
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
diff --git a/server/Cargo.toml b/server/Cargo.toml
index 3c875e90..ebd7b568 100644
--- a/server/Cargo.toml
+++ b/server/Cargo.toml
@@ -18,3 +18,5 @@ env_logger = "*"
rand = "0.6.5"
strum = "0.14.0"
strum_macros = "0.14.0"
+jsonwebtoken = "*"
+regex = "1"
diff --git a/server/migrations/2019-02-26-002946_create_user/up.sql b/server/migrations/2019-02-26-002946_create_user/up.sql
index 577ff136..d4edb370 100644
--- a/server/migrations/2019-02-26-002946_create_user/up.sql
+++ b/server/migrations/2019-02-26-002946_create_user/up.sql
@@ -1,9 +1,9 @@
create table user_ (
id serial primary key,
- name varchar(20) not null,
+ name varchar(20) not null unique,
preferred_username varchar(20),
password_encrypted text not null,
- email text,
+ email text unique,
icon bytea,
published timestamp not null default now(),
updated timestamp
diff --git a/server/migrations/2019-02-27-170003_create_community/up.sql b/server/migrations/2019-02-27-170003_create_community/up.sql
index 30deec5b..1ee2e51d 100644
--- a/server/migrations/2019-02-27-170003_create_community/up.sql
+++ b/server/migrations/2019-02-27-170003_create_community/up.sql
@@ -1,6 +1,6 @@
create table community (
id serial primary key,
- name varchar(20) not null,
+ name varchar(20) not null unique,
published timestamp not null default now(),
updated timestamp
);
diff --git a/server/src/actions/comment.rs b/server/src/actions/comment.rs
index d23382c6..98d5322c 100644
--- a/server/src/actions/comment.rs
+++ b/server/src/actions/comment.rs
@@ -23,14 +23,14 @@ pub struct Comment {
pub updated: Option<chrono::NaiveDateTime>
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="comment"]
-pub struct CommentForm<'a> {
- pub content: &'a str,
- pub attributed_to: &'a str,
- pub post_id: &'a i32,
- pub parent_id: Option<&'a i32>,
- pub updated: Option<&'a chrono::NaiveDateTime>
+pub struct CommentForm {
+ pub content: String,
+ pub attributed_to: String,
+ pub post_id: i32,
+ pub parent_id: Option<i32>,
+ pub updated: Option<chrono::NaiveDateTime>
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@@ -44,59 +44,55 @@ pub struct CommentLike {
pub published: chrono::NaiveDateTime,
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="comment_like"]
-pub struct CommentLikeForm<'a> {
- pub comment_id: &'a i32,
- pub fedi_user_id: &'a str,
- pub score: &'a i16
+pub struct CommentLikeForm {
+ pub comment_id: i32,
+ pub fedi_user_id: String,
+ pub score: i16
}
-impl<'a> Crud<CommentForm<'a>> for Comment {
- fn read(conn: &PgConnection, comment_id: i32) -> Comment {
+impl Crud<CommentForm> for Comment {
+ fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
use schema::comment::dsl::*;
comment.find(comment_id)
- .first::<Comment>(conn)
- .expect("Error in query")
+ .first::<Self>(conn)
}
- fn delete(conn: &PgConnection, comment_id: i32) -> usize {
+ fn delete(conn: &PgConnection, comment_id: i32) -> Result<usize, Error> {
use schema::comment::dsl::*;
diesel::delete(comment.find(comment_id))
.execute(conn)
- .expect("Error deleting.")
}
- fn create(conn: &PgConnection, comment_form: CommentForm) -> Result<Comment, Error> {
+ fn create(conn: &PgConnection, comment_form: &CommentForm) -> Result<Self, Error> {
use schema::comment::dsl::*;
insert_into(comment)
.values(comment_form)
- .get_result::<Comment>(conn)
+ .get_result::<Self>(conn)
}
- fn update(conn: &PgConnection, comment_id: i32, comment_form: CommentForm) -> Comment {
+ fn update(conn: &PgConnection, comment_id: i32, comment_form: &CommentForm) -> Result<Self, Error> {
use schema::comment::dsl::*;
diesel::update(comment.find(comment_id))
.set(comment_form)
- .get_result::<Comment>(conn)
- .expect(&format!("Unable to find {}", comment_id))
+ .get_result::<Self>(conn)
}
}
-impl<'a> Likeable <CommentLikeForm<'a>> for CommentLike {
- fn like(conn: &PgConnection, comment_like_form: CommentLikeForm) -> Result<CommentLike, Error> {
+impl Likeable <CommentLikeForm> for CommentLike {
+ fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
use schema::comment_like::dsl::*;
insert_into(comment_like)
.values(comment_like_form)
- .get_result::<CommentLike>(conn)
+ .get_result::<Self>(conn)
}
- fn remove(conn: &PgConnection, comment_like_form: CommentLikeForm) -> usize {
+ fn remove(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<usize, Error> {
use schema::comment_like::dsl::*;
diesel::delete(comment_like
.filter(comment_id.eq(comment_like_form.comment_id))
- .filter(fedi_user_id.eq(comment_like_form.fedi_user_id)))
+ .filter(fedi_user_id.eq(&comment_like_form.fedi_user_id)))
.execute(conn)
- .expect("Error deleting.")
}
}
@@ -117,17 +113,17 @@ mod tests {
updated: None
};
- let inserted_post = Post::create(&conn, new_post).unwrap();
+ let inserted_post = Post::create(&conn, &new_post).unwrap();
let comment_form = CommentForm {
content: "A test comment".into(),
attributed_to: "test_user.com".into(),
- post_id: &inserted_post.id,
+ post_id: inserted_post.id,
parent_id: None,
updated: None
};
- let inserted_comment = Comment::create(&conn, comment_form).unwrap();
+ let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
let expected_comment = Comment {
id: inserted_comment.id,
@@ -142,20 +138,20 @@ mod tests {
let child_comment_form = CommentForm {
content: "A child comment".into(),
attributed_to: "test_user.com".into(),
- post_id: &inserted_post.id,
- parent_id: Some(&inserted_comment.id),
+ post_id: inserted_post.id,
+ parent_id: Some(inserted_comment.id),
updated: None
};
- let inserted_child_comment = Comment::create(&conn, child_comment_form).unwrap();
+ let inserted_child_comment = Comment::create(&conn, &child_comment_form).unwrap();
let comment_like_form = CommentLikeForm {
- comment_id: &inserted_comment.id,
+ comment_id: inserted_comment.id,
fedi_user_id: "test".into(),
- score: &1
+ score: 1
};
- let inserted_comment_like = CommentLike::like(&conn, comment_like_form).unwrap();
+ let inserted_comment_like = CommentLike::like(&conn, &comment_like_form).unwrap();
let expected_comment_like = CommentLike {
id: inserted_comment_like.id,
@@ -165,12 +161,12 @@ mod tests {
score: 1
};
- let read_comment = Comment::read(&conn, inserted_comment.id);
- let updated_comment = Comment::update(&conn, inserted_comment.id, comment_form);
- let like_removed = CommentLike::remove(&conn, comment_like_form);
- let num_deleted = Comment::delete(&conn, inserted_comment.id);
- Comment::delete(&conn, inserted_child_comment.id);
- Post::delete(&conn, inserted_post.id);
+ let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
+ let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
+ let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
+ let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
+ Comment::delete(&conn, inserted_child_comment.id).unwrap();
+ Post::delete(&conn, inserted_post.id).unwrap();
assert_eq!(expected_comment, read_comment);
assert_eq!(expected_comment, inserted_comment);
diff --git a/server/src/actions/community.rs b/server/src/actions/community.rs
index 03490369..44d7b749 100644
--- a/server/src/actions/community.rs
+++ b/server/src/actions/community.rs
@@ -2,9 +2,10 @@ extern crate diesel;
use schema::{community, community_user, community_follower};
use diesel::*;
use diesel::result::Error;
+use serde::{Deserialize, Serialize};
use {Crud, Followable, Joinable};
-#[derive(Queryable, Identifiable, PartialEq, Debug)]
+#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
#[table_name="community"]
pub struct Community {
pub id: i32,
@@ -13,11 +14,11 @@ pub struct Community {
pub updated: Option<chrono::NaiveDateTime>
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize)]
#[table_name="community"]
-pub struct CommunityForm<'a> {
- pub name: &'a str,
- pub updated: Option<&'a chrono::NaiveDateTime>
+pub struct CommunityForm {
+ pub name: String,
+ pub updated: Option<chrono::NaiveDateTime>
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@@ -30,11 +31,11 @@ pub struct CommunityUser {
pub published: chrono::NaiveDateTime,
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="community_user"]
-pub struct CommunityUserForm<'a> {
- pub community_id: &'a i32,
- pub fedi_user_id: &'a str,
+pub struct CommunityUserForm {
+ pub community_id: i32,
+ pub fedi_user_id: String,
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@@ -47,76 +48,72 @@ pub struct CommunityFollower {
pub published: chrono::NaiveDateTime,
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="community_follower"]
-pub struct CommunityFollowerForm<'a> {
- pub community_id: &'a i32,
- pub fedi_user_id: &'a str,
+pub struct CommunityFollowerForm {
+ pub community_id: i32,
+ pub fedi_user_id: String,
}
-impl<'a> Crud<CommunityForm<'a>> for Community {
- fn read(conn: &PgConnection, community_id: i32) -> Community {
+impl Crud<CommunityForm> for Community {
+ fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> {
use schema::community::dsl::*;
community.find(community_id)
- .first::<Community>(conn)
- .expect("Error in query")
+ .first::<Self>(conn)
}
- fn delete(conn: &PgConnection, community_id: i32) -> usize {
+ fn delete(conn: &PgConnection, community_id: i32) -> Result<usize, Error> {
use schema::community::dsl::*;
diesel::delete(community.find(community_id))
.execute(conn)
- .expect("Error deleting.")
}
- fn create(conn: &PgConnection, new_community: CommunityForm) -> Result<Community, Error> {
+ fn create(conn: &PgConnection, new_community: &CommunityForm) -> Result<Self, Error> {
use schema::community::dsl::*;
insert_into(community)
.values(new_community)
- .get_result::<Community>(conn)
+ .get_result::<Self>(conn)
}
- fn update(conn: &PgConnection, community_id: i32, new_community: CommunityForm) -> Community {
+ fn update(conn: &PgConnection, community_id: i32, new_community: &CommunityForm) -> Result<Self, Error> {
use schema::community::dsl::*;
diesel::update(community.find(community_id))
.set(new_community)
- .get_result::<Community>(conn)
- .expect(&format!("Unable to find {}", community_id))
+ .get_result::<Self>(conn)
}
}
-impl<'a> Followable<CommunityFollowerForm<'a>> for CommunityFollower {
- fn follow(conn: &PgConnection, community_follower_form: CommunityFollowerForm) -> Result<CommunityFollower, Error> {
+impl Followable<CommunityFollowerForm> for CommunityFollower {
+ fn follow(conn: &PgConnection, community_follower_form: &CommunityFollowerForm) -> Result<Self, Error> {
use schema::community_follower::dsl::*;
insert_into(community_follower)
.values(community_follower_form)
- .get_result::<CommunityFollower>(conn)
+ .get_result::<Self>(conn)
}
- fn ignore(conn: &PgConnection, community_follower_form: CommunityFollowerForm) -> usize {
+ fn ignore(conn: &PgConnection, community_follower_form: &CommunityFollowerForm) -> Result<usize, Error> {
use schema::community_follower::dsl::*;
diesel::delete(community_follower
- .filter(community_id.eq(community_follower_form.community_id))
- .filter(fedi_user_id.eq(community_follower_form.fedi_user_id)))
+ .filter(community_id.eq(&community_follower_form.community_id))
+ .filter(fedi_user_id.eq(&community_follower_form.fedi_user_id)))
.execute(conn)
- .expect("Error deleting.")
}
}
-impl<'a> Joinable<CommunityUserForm<'a>> for CommunityUser {
- fn join(conn: &PgConnection, community_user_form: CommunityUserForm) -> Result<CommunityUser, Error> {
+impl Joinable<CommunityUserForm> for CommunityUser {
+ fn join(conn: &PgConnection, community_user_form: &CommunityUserForm) -> Result<Self, Error> {
use schema::community_user::dsl::*;
insert_into(community_user)
.values(community_user_form)
- .get_result::<CommunityUser>(conn)
+ .get_result::<Self>(conn)
}
- fn leave(conn: &PgConnection, community_user_form: CommunityUserForm) -> usize {
+
+ fn leave(conn: &PgConnection, community_user_form: &CommunityUserForm) -> Result<usize, Error> {
use schema::community_user::dsl::*;
diesel::delete(community_user
.filter(community_id.eq(community_user_form.community_id))
- .filter(fedi_user_id.eq(community_user_form.fedi_user_id)))
+ .filter(fedi_user_id.eq(&community_user_form.fedi_user_id)))
.execute(conn)
- .expect("Error deleting.")
}
}
@@ -135,7 +132,7 @@ mod tests {
updated: None
};
- let inserted_community = Community::create(&conn, new_community).unwrap();
+ let inserted_community = Community::create(&conn, &new_community).unwrap();
let expected_community = Community {
id: inserted_community.id,
@@ -145,21 +142,21 @@ mod tests {
};
let new_user = UserForm {
- name: "thom".into(),
+ name: "terry".into(),
preferred_username: None,
password_encrypted: "nope".into(),
email: None,
updated: None
};
- let inserted_user = User_::create(&conn, new_user).unwrap();
+ let inserted_user = User_::create(&conn, &new_user).unwrap();
let community_follower_form = CommunityFollowerForm {
- community_id: &inserted_community.id,
+ community_id: inserted_community.id,
fedi_user_id: "test".into()
};
- let inserted_community_follower = CommunityFollower::follow(&conn, community_follower_form).unwrap();
+ let inserted_community_follower = CommunityFollower::follow(&conn, &community_follower_form).unwrap();
let expected_community_follower = CommunityFollower {
id: inserted_community_follower.id,
@@ -169,11 +166,11 @@ mod tests {
};
let community_user_form = CommunityUserForm {
- community_id: &inserted_community.id,
+ community_id: inserted_community.id,
fedi_user_id: "test".into()
};
- let inserted_community_user = CommunityUser::join(&conn, community_user_form).unwrap();
+ let inserted_community_user = CommunityUser::join(&conn, &community_user_form).unwrap();
let expected_community_user = CommunityUser {
id: inserted_community_user.id,
@@ -182,12 +179,12 @@ mod tests {
published: inserted_community_user.published
};
- let read_community = Community::read(&conn, inserted_community.id);
- let updated_community = Community::update(&conn, inserted_community.id, new_community);
- let ignored_community = CommunityFollower::ignore(&conn, community_follower_form);
- let left_community = CommunityUser::leave(&conn, community_user_form);
- let num_deleted = Community::delete(&conn, inserted_community.id);
- User_::delete(&conn, inserted_user.id);
+ let read_community = Community::read(&conn, inserted_community.id).unwrap();
+ let updated_community = Community::update(&conn, inserted_community.id, &new_community).unwrap();
+ let ignored_community = CommunityFollower::ignore(&conn, &community_follower_form).unwrap();
+ let left_community = CommunityUser::leave(&conn, &community_user_form).unwrap();
+ let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
+ User_::delete(&conn, inserted_user.id).unwrap();
assert_eq!(expected_community, read_community);
assert_eq!(expected_community, inserted_community);
diff --git a/server/src/actions/post.rs b/server/src/actions/post.rs
index dd80f582..889fcf03 100644
--- a/server/src/actions/post.rs
+++ b/server/src/actions/post.rs
@@ -15,13 +15,13 @@ pub struct Post {
pub updated: Option<chrono::NaiveDateTime>
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="post"]
-pub struct PostForm<'a> {
- pub name: &'a str,
- pub url: &'a str,
- pub attributed_to: &'a str,
- pub updated: Option<&'a chrono::NaiveDateTime>
+pub struct PostForm {
+ pub name: String,
+ pub url: String,
+ pub attributed_to: String,
+ pub updated: Option<chrono::NaiveDateTime>
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
@@ -35,59 +35,55 @@ pub struct PostLike {
pub published: chrono::NaiveDateTime,
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="post_like"]
-pub struct PostLikeForm<'a> {
- pub post_id: &'a i32,
- pub fedi_user_id: &'a str,
- pub score: &'a i16
+pub struct PostLikeForm {
+ pub post_id: i32,
+ pub fedi_user_id: String,
+ pub score: i16
}
-impl<'a> Crud<PostForm<'a>> for Post {
- fn read(conn: &PgConnection, post_id: i32) -> Post {
+impl Crud<PostForm> for Post {
+ fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
use schema::post::dsl::*;
post.find(post_id)
- .first::<Post>(conn)
- .expect("Error in query")
+ .first::<Self>(conn)
}
- fn delete(conn: &PgConnection, post_id: i32) -> usize {
+ fn delete(conn: &PgConnection, post_id: i32) -> Result<usize, Error> {
use schema::post::dsl::*;
diesel::delete(post.find(post_id))
.execute(conn)
- .expect("Error deleting.")
}
- fn create(conn: &PgConnection, new_post: PostForm) -> Result<Post, Error> {
+ fn create(conn: &PgConnection, new_post: &PostForm) -> Result<Self, Error> {
use schema::post::dsl::*;
insert_into(post)
.values(new_post)
- .get_result::<Post>(conn)
+ .get_result::<Self>(conn)
}
- fn update(conn: &PgConnection, post_id: i32, new_post: PostForm) -> Post {
+ fn update(conn: &PgConnection, post_id: i32, new_post: &PostForm) -> Result<Self, Error> {
use schema::post::dsl::*;
diesel::update(post.find(post_id))
.set(new_post)
- .get_result::<Post>(conn)
- .expect(&format!("Unable to find {}", post_id))
+ .get_result::<Self>(conn)
}
}
-impl<'a> Likeable <PostLikeForm<'a>> for PostLike {
- fn like(conn: &PgConnection, post_like_form: PostLikeForm) -> Result<PostLike, Error> {
+impl Likeable <PostLikeForm> for PostLike {
+ fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
use schema::post_like::dsl::*;
insert_into(post_like)
.values(post_like_form)
- .get_result::<PostLike>(conn)
+ .get_result::<Self>(conn)
}
- fn remove(conn: &PgConnection, post_like_form: PostLikeForm) -> usize {
+ fn remove(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<usize, Error> {
use schema::post_like::dsl::*;
diesel::delete(post_like
.filter(post_id.eq(post_like_form.post_id))
- .filter(fedi_user_id.eq(post_like_form.fedi_user_id)))
+ .filter(fedi_user_id.eq(&post_like_form.fedi_user_id)))
.execute(conn)
- .expect("Error deleting.")
}
}
@@ -107,7 +103,7 @@ mod tests {
updated: None
};
- let inserted_post = Post::create(&conn, new_post).unwrap();
+ let inserted_post = Post::create(&conn, &new_post).unwrap();
let expected_post = Post {
id: inserted_post.id,
@@ -119,12 +115,12 @@ mod tests {
};
let post_like_form = PostLikeForm {
- post_id: &inserted_post.id,
+ post_id: inserted_post.id,
fedi_user_id: "test".into(),
- score: &1
+ score: 1
};
- let inserted_post_like = PostLike::like(&conn, post_like_form).unwrap();
+ let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
let expected_post_like = PostLike {
id: inserted_post_like.id,
@@ -134,10 +130,10 @@ mod tests {
score: 1
};
- let read_post = Post::read(&conn, inserted_post.id);
- let updated_post = Post::update(&conn, inserted_post.id, new_post);
- let like_removed = PostLike::remove(&conn, post_like_form);
- let num_deleted = Post::delete(&conn, inserted_post.id);
+ let read_post = Post::read(&conn, inserted_post.id).unwrap();
+ let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
+ let like_removed = PostLike::remove(&conn, &post_like_form).unwrap();
+ let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
assert_eq!(expected_post, read_post);
assert_eq!(expected_post, inserted_post);
diff --git a/server/src/actions/user.rs b/server/src/actions/user.rs
index 8556525f..6016580d 100644
--- a/server/src/actions/user.rs
+++ b/server/src/actions/user.rs
@@ -1,9 +1,11 @@
-extern crate diesel;
use schema::user_;
use diesel::*;
use diesel::result::Error;
use schema::user_::dsl::*;
-use Crud;
+use serde::{Serialize, Deserialize};
+use {Crud,is_email_regex};
+use jsonwebtoken::{encode, decode, Header, Validation};
+use bcrypt::{DEFAULT_COST, hash};
#[derive(Queryable, Identifiable, PartialEq, Debug)]
#[table_name="user_"]
@@ -18,43 +20,75 @@ pub struct User_ {
pub updated: Option<chrono::NaiveDateTime>
}
-#[derive(Insertable, AsChangeset, Clone, Copy)]
+#[derive(Insertable, AsChangeset, Clone)]
#[table_name="user_"]
-pub struct UserForm<'a> {
- pub name: &'a str,
- pub preferred_username: Option<&'a str>,
- pub password_encrypted: &'a str,
- pub email: Option<&'a str>,
- pub updated: Option<&'a chrono::NaiveDateTime>
+pub struct UserForm {
+ pub name: String,
+ pub preferred_username: Option<String>,
+ pub password_encrypted: String,
+ pub email: Option<String>,
+ pub updated: Option<chrono::NaiveDateTime>
}
-impl<'a> Crud<UserForm<'a>> for User_ {
- fn read(conn: &PgConnection, user_id: i32) -> User_ {
+impl Crud<UserForm> for User_ {
+ fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
user_.find(user_id)
- .first::<User_>(conn)
- .expect("Error in query")
+ .first::<Self>(conn)
}
- fn delete(conn: &PgConnection, user_id: i32) -> usize {
+ fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
diesel::delete(user_.find(user_id))
.execute(conn)
- .expect("Error deleting.")
}
- fn create(conn: &PgConnection, form: UserForm) -> Result<User_, Error> {
+ fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
let mut edited_user = form.clone();
- // Add the rust crypt
- edited_user.password_encrypted = "here";
- // edited_user.password_encrypted;
- insert_into(user_)
- .values(edited_user)
- .get_result::<User_>(conn)
+ let password_hash = hash(&form.password_encrypted, DEFAULT_COST)
+ .expect("Couldn't hash password");
+ edited_user.password_encrypted = password_hash;
+ insert_into(user_)
+ .values(edited_user)
+ .get_result::<Self>(conn)
}
- fn update(conn: &PgConnection, user_id: i32, form: UserForm) -> User_ {
+ fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
let mut edited_user = form.clone();
- edited_user.password_encrypted = "here";
+ let password_hash = hash(&form.password_encrypted, DEFAULT_COST)
+ .expect("Couldn't hash password");
+ edited_user.password_encrypted = password_hash;
diesel::update(user_.find(user_id))
.set(edited_user)
- .get_result::<User_>(conn)
- .expect(&format!("Unable to find user {}", user_id))
+ .get_result::<Self>(conn)
+ }
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+struct Claims {
+ id: i32,
+ username: String
+}
+
+type Jwt = String;
+impl User_ {
+ pub fn jwt(&self) -> Jwt {
+ let my_claims = Claims {
+ id: self.id,
+ username: self.name.to_owned()
+ };
+ encode(&Header::default(), &my_claims, "secret".as_ref()).unwrap()
+ }
+
+ pub fn find_by_email_or_username(conn: &PgConnection, username_or_email: &str) -> Result<Self, Error> {
+ if is_email_regex(username_or_email) {
+ user_.filter(email.eq(username_or_email))
+ .first::<User_>(conn)
+ } else {
+ user_.filter(name.eq(username_or_email))
+ .first::<User_>(conn)
+ }
+ }
+
+ pub fn find_by_jwt(conn: &PgConnection, jwt: &str) -> Result<Self, Error> {
+ let token = decode::<Claims>(&jwt, "secret".as_ref(), &Validation::default())
+ .expect("Couldn't decode jwt");
+ Self::read(&conn, token.claims.id)
}
}
@@ -75,26 +109,26 @@ mod tests {
updated: None
};
- let inserted_user = User_::create(&conn, new_user).unwrap();
+ let inserted_user = User_::create(&conn, &new_user).unwrap();
let expected_user = User_ {
id: inserted_user.id,
name: "thom".into(),
preferred_username: None,
- password_encrypted: "here".into(),
+ password_encrypted: "$2y$12$YXpNpYsdfjmed.QlYLvw4OfTCgyKUnKHc/V8Dgcf9YcVKHPaYXYYy".into(),
email: None,
icon: None,
published: inserted_user.published,
updated: None
};
- let read_user = User_::read(&conn, inserted_user.id);
- let updated_user = User_::update(&conn, inserted_user.id, new_user);
- let num_de