Skip to content

Commit

Permalink
Merge pull request #49 from kochamaltki/chlopczyk
Browse files Browse the repository at this point in the history
image uplaod & reactions
  • Loading branch information
malinowy5 authored Apr 3, 2024
2 parents 910513e + 8e8d99a commit 277d68b
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 104 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Cargo CI

on:
push:
branches: [ main ]
branches: [ main, chlopczyk ]
pull_request:
branches: [ main ]

Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ jsonwebtoken = "=7.2"
time = "0.3"
tracing = "0.1"
tracing-subscriber = "0.3"
uuid = { version = "0.8", features = ["v4"] }
futures = { version = "0.3", default-features = false }
bytes = "1.0"
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,18 @@
#### /api/get/user/id/{name}
- Get: 200 (i64) / 404 ("User not found")
- Note: Get id of user {name} (-1 if there is no such user)
#### /api/get/reactions/from-post/{id}
- Get: 200 (ReactionCountMap) / 404 ("Post not found")
- Note: Get (reaction, count) map from post {id}
#### /api/get/likes/from-post/{id}
- Get: 200 (LikeCountMap) / 404 ("Post not found")
- Note: Get (like, count) map from post {id}
#### /api/post/add-post
- Post: PostCreateRequest
- Effect: Adds a post to the db
- Return: 201 ("Post created") / 401 ("Wrong token" / "User is banned") / 404 ("User not found")
- Headers: 'Content-Type: application/json' 'Content-Type: text/plain'
#### /api/post/react
- Post: ReactRequest
- Effects: Adds reaction to a post
- Return: 200 ("Reaction added") / 406 ("Reaction already exists")
- Effects: Adds like to a post
- Return: 200 ("Like added") / 406 ("Like already exists")
- Headers: 'Content-Type: application/json' 'Content-Type: text/plain'
#### /api/post/login
- Post: LoginRequest
Expand Down Expand Up @@ -89,8 +89,8 @@ TagList {
}
```
```
ReactionCountMap {
reaction_count_map: map(i64, i64)
LikeCountMap {
like_count_map: map(i64, i64)
}
```
```
Expand All @@ -114,7 +114,7 @@ PostCreateRequest {
```
ReactRequest {
post_id: i64
reaction_type: i64
like_type: i64
token: string
}
```
Expand Down
2 changes: 2 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/bin/bash

mkdir -p ./media/profile-pictures
mkdir -p ./media/images
touch SECRET
./setup-db.sh
./build.sh
Expand Down
49 changes: 30 additions & 19 deletions setup.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ DROP TABLE IF EXISTS posts;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS posts_tags;
DROP TABLE IF EXISTS tags;
DROP TABLE IF EXISTS reactions;
DROP TABLE IF EXISTS likes;
DROP TABLE IF EXISTS images;
DROP TABLE IF EXISTS posts_images;

CREATE TABLE posts(
post_id INTEGER PRIMARY KEY NOT NULL,
Expand Down Expand Up @@ -31,27 +33,36 @@ CREATE TABLE users(
is_banned INTEGER NOT NULL
);

CREATE TABLE reactions(
type INTEGER NOT NULL,
CREATE TABLE likes(
user_id INTEGER NOT NULL,
post_id INTEGER NOT NULL
);

-- ------------- ----------- ---------------- ____________
-- | users | | posts | | posts_tags | | tags |
-- ------------- ----------- ---------------- ------------
-- | user_id | 1 -| |------- 1 | post_id | 1 - many | post_id | |- 1 | tag_id |
-- | user_name | |--------------------------- ---- many | user_id | | tag_id | many -| | tag_name |
-- | passwd | | | | date | ---------------- ------------
-- | is_admin | | | | body |
-- | is_banned | | | -----------
-- ------------- | |
-- | ------------- |
-- | | reactions | |
-- | ------------- |
-- | | type | |
-- |- many | user_id | |
-- | post_id | many -|
-- -------------
CREATE TABLE posts_images(
post_id INTEGER NOT NULL,
image_uuid VARCHAR(34) NOT NULL
);

CREATE TABLE images(
image_uuid VARCHAR(34) NOT NULL
);

-- ---------------- ----------- ---------------- ____________
-- | users | | posts | | posts_tags | | tags |
-- ---------------- ----------- ---------------- ------------
-- | user_id | 1 -| |------- 1 | post_id | 1 - many | post_id | |- 1 | tag_id |
-- | user_name | |--------------------------- ---- many | user_id | | tag_id | many -| | tag_name |
-- | display_name | | | | date | ---------------- ------------
-- | description | | | | body |
-- | passwd | | | -----------
-- | is_admin | | |
-- | is_banned | | |
-- ---------------- | |
-- | ------------- |
-- | | likes | |
-- | ------------- |
-- |- many | user_id | |
-- | post_id | many -|
-- -------------

INSERT INTO users VALUES (0, 'root', 'gigachadadmin', 'hala madrid', 'toor', 1, 0);
74 changes: 60 additions & 14 deletions src/api_calls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ use std::collections::HashMap;

use jsonwebtoken::TokenData;
use tokio_rusqlite::params;
use tracing::info;
use tracing::{error, info};
use warp::filters::multipart::FormData;
use warp::Filter;

use bytes::BufMut;
use futures::{StreamExt, TryStreamExt};
use crate::get_token::get_token;
use crate::verify_token::{self, Claims};
use crate::types::*;
Expand Down Expand Up @@ -295,8 +297,8 @@ pub async fn get_user_id(user_name: String) -> Result<impl warp::Reply, warp::Re
))
}

pub async fn get_reactions_from_post(post_id: i64) -> Result<impl warp::Reply, warp::Rejection> {
let query = "SELECT type, COUNT(user_id) FROM reactions WHERE post_id = ? GROUP BY type";
pub async fn get_likes_from_post(post_id: i64) -> Result<impl warp::Reply, warp::Rejection> {
let query = "SELECT type, COUNT(user_id) FROM likes WHERE post_id = ? GROUP BY type";
let connection = tokio_rusqlite::Connection::open("projekt-db").await.unwrap();

if !check_post(&connection, post_id).await {
Expand All @@ -307,22 +309,22 @@ pub async fn get_reactions_from_post(post_id: i64) -> Result<impl warp::Reply, w
));
}

let reaction_count_map = connection.call(move |conn| {
let like_count_map = connection.call(move |conn| {
let mut statement = conn.prepare(query).unwrap();
let mut rows = statement.query(params![post_id]).unwrap();
let mut reactions_map: HashMap<i64, i64> = HashMap::new();
let mut likes_map: HashMap<i64, i64> = HashMap::new();
while let Ok(Some(row)) = rows.next() {
reactions_map.insert(row.get(0).unwrap(), row.get(1).unwrap());
likes_map.insert(row.get(0).unwrap(), row.get(1).unwrap());
}
Ok(reactions_map)
Ok(likes_map)
}).await.unwrap();

let reactions = ReactionCountMap {
reaction_count_map
let likes = LikeCountMap {
like_count_map
};

Ok(warp::reply::with_status(
warp::reply::json(&reactions),
warp::reply::json(&likes),
warp::http::StatusCode::OK
))
}
Expand Down Expand Up @@ -413,16 +415,16 @@ pub async fn react(request: ReactRequest) -> Result<impl warp::Reply, warp::Reje
));
}

let existed = add_reaction_db(&connection, token.claims.uid, request.post_id, request.reaction_type).await;
let existed = add_like_db(&connection, token.claims.uid, request.post_id, request.like_type).await;

if existed {
let r = "Reaction already exists";
let r = "Like already exists";
Ok(warp::reply::with_status(
warp::reply::json(&r),
warp::http::StatusCode::NOT_ACCEPTABLE,
))
} else {
let r = "Reaction added";
let r = "Like added";
Ok(warp::reply::with_status(
warp::reply::json(&r),
warp::http::StatusCode::OK,
Expand Down Expand Up @@ -655,6 +657,50 @@ pub async fn change_display_name(request: DisplayNameChangeRequest) -> Result<im
}
}

pub async fn upload_image(form: FormData) -> Result<impl warp::Reply, warp::Rejection> {
let mut parts = form.into_stream();
while let Some(Ok(p)) = parts.next().await {
if p.name() == "file" {
let content_type = p.content_type();
let file_ending;
match content_type {
Some(file_type) => match file_type {
"image/png" => {
file_ending = "png";
}
v => {
error!("invalid file type found: {}", v);
return Err(warp::reject::reject());
}
},
None => {
error!("file type could not be determined");
return Err(warp::reject::reject());
}
}
let value = p
.stream()
.try_fold(Vec::new(), |mut vec, data| {
vec.put(data);
async move { Ok(vec) }
})
.await
.map_err(|e| {
error!("reading file error: {}", e);
warp::reject::reject()
})?;
let image_uuid = uuid::Uuid::new_v4().to_string();
let file_name = format!("./media/images/{}.{}", image_uuid, file_ending);
tokio::fs::write(&file_name, value).await.map_err(|e| {
error!("error writing file: {}", e);
warp::reject::reject()
})?;
info!("created file: {}", file_name);
}
}
Ok("success")
}

pub fn post_json() -> impl Filter<Extract = (PostCreateRequest,), Error = warp::Rejection> + Clone {
warp::body::content_length_limit(1024 * 16).and(warp::body::json())
}
Expand Down
22 changes: 11 additions & 11 deletions src/database_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ pub async fn purge_data(connection: &Connection, user_id: i64) {
}).await.unwrap();
}

let reactions_delete_query = "DELETE FROM reactions WHERE user_id = ?";
let likes_delete_query = "DELETE FROM likes WHERE user_id = ?";
connection.call(move |conn| {
let mut statement = conn.prepare(reactions_delete_query).unwrap();
let mut statement = conn.prepare(likes_delete_query).unwrap();
statement.execute(params![user_id]).unwrap();
Ok(0)
}).await.unwrap();
Expand Down Expand Up @@ -269,12 +269,12 @@ pub async fn get_id_passwd_adm(connection: &Connection, user: String) -> Result<

}

pub async fn check_reaction(connection: &Connection, user_id: i64, post_id: i64, reaction_type: i64) -> bool {
let query = "SELECT post_id FROM reactions WHERE type = ? AND user_id = ? AND post_id = ?";
pub async fn check_like(connection: &Connection, user_id: i64, post_id: i64, like_type: i64) -> bool {
let query = "SELECT post_id FROM likes WHERE post_id = ?";

connection.call(move |conn| {
let mut statement = conn.prepare(query).unwrap();
let mut rows = statement.query(params![reaction_type, user_id, post_id]).unwrap();
let mut rows = statement.query(params![like_type, user_id, post_id]).unwrap();
if let Ok(Some(_)) = rows.next() {
Ok(true)
} else {
Expand All @@ -283,21 +283,21 @@ pub async fn check_reaction(connection: &Connection, user_id: i64, post_id: i64,
}).await.unwrap()
}

pub async fn add_reaction_db(connection: &Connection, user_id: i64, post_id: i64, reaction_type: i64) -> bool {
let query = "INSERT INTO reactions VALUES (?, ?, ?)";
pub async fn add_like_db(connection: &Connection, user_id: i64, post_id: i64, like_type: i64) -> bool {
let query = "INSERT INTO likes VALUES (?, ?, ?)";

if check_reaction(connection, user_id, post_id, reaction_type).await {
info!("Reaction already exists");
if check_like(connection, user_id, post_id, like_type).await {
info!("Like already exists");
return true;
}

connection.call(move |conn| {
let mut statement = conn.prepare(query).unwrap();
statement.execute(params![reaction_type, user_id, post_id]).unwrap();
statement.execute(params![like_type, user_id, post_id]).unwrap();
Ok(0)
}).await.unwrap();

info!("Reaction {} added for post {} by user {}", reaction_type, post_id, user_id);
info!("Like {} added for post {} by user {}", like_type, post_id, user_id);
false
}

18 changes: 12 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ pub fn routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
.and(warp::path::end())
.and_then(get_profile_by_id);

let get_reactions_from_post = warp::get()
let get_likes_from_post = warp::get()
.and(warp::path("api"))
.and(warp::path("get"))
.and(warp::path("reactions"))
.and(warp::path("likes"))
.and(warp::path("from-post"))
.and(warp::path::param())
.and(warp::path::end())
.and_then(get_reactions_from_post);
.and_then(get_likes_from_post);

let get_profile_picture = warp::get()
.and(warp::path("api"))
Expand Down Expand Up @@ -179,8 +179,14 @@ pub fn routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
.and(warp::path::end())
.and(display_name_change_json())
.and_then(change_display_name);


let upload_image = warp::post()
.and(warp::path("api"))
.and(warp::path("post"))
.and(warp::path("upload"))
.and(warp::path("image"))
.and(warp::multipart::form().max_length(25000000))
.and_then(upload_image);

get_posts_by_user
.or(post)
Expand All @@ -196,10 +202,11 @@ pub fn routes() -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejecti
.or(get_posts_by_tag)
.or(get_tags_from_post)
.or(react)
.or(get_reactions_from_post)
.or(get_likes_from_post)
.or(get_profile_by_id)
.or(get_profile_picture)
.or(change_display_name)
.or(upload_image)
// .or(get_posts_from_search)
// .or(get_users_from_search)
}
Expand All @@ -210,5 +217,4 @@ async fn main() {
let cors = warp::cors().allow_any_origin();
let routes = routes().with(cors);
warp::serve(routes).run(([127, 0, 0, 1], 8000)).await;

}
6 changes: 3 additions & 3 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ pub struct TagList {
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ReactionCountMap {
pub reaction_count_map: HashMap<i64, i64>
pub struct LikeCountMap {
pub like_count_map: HashMap<i64, i64>
}

#[derive(Debug, Deserialize, Serialize, Clone)]
Expand All @@ -60,7 +60,7 @@ pub struct PostCreateRequest {
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct ReactRequest {
pub post_id: i64,
pub reaction_type: i64,
pub like_type: i64,
pub token: String
}

Expand Down
Loading

0 comments on commit 277d68b

Please sign in to comment.