Add Favorite GET, and POST endpoints
This commit is contained in:
1
migrations/2020-08-08-015035_favorites/down.sql
Normal file
1
migrations/2020-08-08-015035_favorites/down.sql
Normal file
@@ -0,0 +1 @@
|
|||||||
|
DROP TABLE favorites
|
||||||
5
migrations/2020-08-08-015035_favorites/up.sql
Normal file
5
migrations/2020-08-08-015035_favorites/up.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE favorites (
|
||||||
|
id INTEGER PRIMARY KEY NOT NULL,
|
||||||
|
userid INTEGER NOT NULL,
|
||||||
|
path TEXT NOT NULL
|
||||||
|
)
|
||||||
@@ -79,3 +79,8 @@ pub struct CreateAccountRequest {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
pub confirmation: String,
|
pub confirmation: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct AddFavoriteRequest {
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use diesel::prelude::*;
|
|||||||
use diesel::sqlite::SqliteConnection;
|
use diesel::sqlite::SqliteConnection;
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
|
||||||
use crate::database::models::{InsertUser, User};
|
use crate::database::models::{Favorite, InsertFavorite, InsertUser, User};
|
||||||
|
|
||||||
mod models;
|
mod models;
|
||||||
mod schema;
|
mod schema;
|
||||||
@@ -68,3 +68,25 @@ pub fn user_exists(name: &str) -> bool {
|
|||||||
.first()
|
.first()
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_favorite(user_id: i32, favorite_path: String) {
|
||||||
|
use schema::favorites::dsl::*;
|
||||||
|
|
||||||
|
let connection = connect();
|
||||||
|
diesel::insert_into(favorites)
|
||||||
|
.values(InsertFavorite {
|
||||||
|
userid: &user_id,
|
||||||
|
path: &favorite_path,
|
||||||
|
})
|
||||||
|
.execute(&connection)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_favorites(user_id: i32) -> Vec<Favorite> {
|
||||||
|
use schema::favorites::dsl::*;
|
||||||
|
|
||||||
|
favorites
|
||||||
|
.filter(userid.eq(user_id))
|
||||||
|
.load::<Favorite>(&connect())
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::database::schema::users;
|
use crate::database::schema::{favorites, users};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Insertable)]
|
#[derive(Insertable)]
|
||||||
@@ -15,3 +15,17 @@ pub struct User {
|
|||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[table_name = "favorites"]
|
||||||
|
pub struct InsertFavorite<'a> {
|
||||||
|
pub userid: &'a i32,
|
||||||
|
pub path: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Queryable, Clone, Debug)]
|
||||||
|
pub struct Favorite {
|
||||||
|
pub id: i32,
|
||||||
|
pub userid: i32,
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
table! {
|
||||||
|
favorites (id) {
|
||||||
|
id -> Integer,
|
||||||
|
userid -> Integer,
|
||||||
|
path -> Text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
users (id) {
|
users (id) {
|
||||||
id -> Integer,
|
id -> Integer,
|
||||||
@@ -5,3 +13,5 @@ table! {
|
|||||||
password -> Text,
|
password -> Text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allow_tables_to_appear_in_same_query!(favorites, users,);
|
||||||
|
|||||||
30
src/main.rs
30
src/main.rs
@@ -6,14 +6,14 @@ use actix_files::NamedFile;
|
|||||||
use actix_web::web::{HttpRequest, HttpResponse, Json};
|
use actix_web::web::{HttpRequest, HttpResponse, Json};
|
||||||
use actix_web::{get, post, web, App, HttpServer, Responder};
|
use actix_web::{get, post, web, App, HttpServer, Responder};
|
||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use data::{LoginRequest, ThumbnailRequest};
|
use data::{AddFavoriteRequest, LoginRequest, ThumbnailRequest};
|
||||||
use jsonwebtoken::{encode, EncodingKey, Header};
|
use jsonwebtoken::{encode, EncodingKey, Header};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::data::{secret_key, Claims, CreateAccountRequest, Token};
|
use crate::data::{secret_key, Claims, CreateAccountRequest, Token};
|
||||||
use crate::database::{create_user, get_user, user_exists};
|
use crate::database::{add_favorite, create_user, get_favorites, get_user, user_exists};
|
||||||
use crate::files::{is_valid_path, list_files};
|
use crate::files::{is_valid_path, list_files};
|
||||||
use crate::video::*;
|
use crate::video::*;
|
||||||
|
|
||||||
@@ -170,6 +170,28 @@ async fn get_video_part(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("image/favorites")]
|
||||||
|
async fn favorites(claims: Claims) -> impl Responder {
|
||||||
|
let favorites = get_favorites(claims.sub.parse::<i32>().unwrap())
|
||||||
|
.into_iter()
|
||||||
|
.map(|favorite| favorite.path)
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
HttpResponse::Ok().json(PhotosResponse {
|
||||||
|
photos: &favorites,
|
||||||
|
dirs: &Vec::new(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("image/favorites")]
|
||||||
|
async fn post_add_favorite(claims: Claims, body: web::Json<AddFavoriteRequest>) -> impl Responder {
|
||||||
|
if let Ok(user_id) = claims.sub.parse::<i32>() {
|
||||||
|
add_favorite(user_id, body.path.clone());
|
||||||
|
HttpResponse::Ok()
|
||||||
|
} else {
|
||||||
|
HttpResponse::BadRequest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn create_thumbnails() {
|
async fn create_thumbnails() {
|
||||||
let thumbs = &dotenv::var("THUMBNAILS").expect("THUMBNAILS not defined");
|
let thumbs = &dotenv::var("THUMBNAILS").expect("THUMBNAILS not defined");
|
||||||
let thumbnail_directory: &Path = Path::new(thumbs);
|
let thumbnail_directory: &Path = Path::new(thumbs);
|
||||||
@@ -206,7 +228,7 @@ async fn create_thumbnails() {
|
|||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let relative_path = &path.strip_prefix(&images).unwrap();
|
let relative_path = &path.strip_prefix(&images).unwrap();
|
||||||
let thumb_path = Path::new(thumbnail_directory).join(relative_path);
|
let thumb_path = Path::new(thumbnail_directory).join(relative_path);
|
||||||
return !thumb_path.exists();
|
!thumb_path.exists()
|
||||||
})
|
})
|
||||||
.map(|entry| (image::open(entry.path()), entry.path().to_path_buf()))
|
.map(|entry| (image::open(entry.path()), entry.path().to_path_buf()))
|
||||||
.filter(|(img, _)| img.is_ok())
|
.filter(|(img, _)| img.is_ok())
|
||||||
@@ -238,6 +260,8 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.service(generate_video)
|
.service(generate_video)
|
||||||
.service(stream_video)
|
.service(stream_video)
|
||||||
.service(get_video_part)
|
.service(get_video_part)
|
||||||
|
.service(favorites)
|
||||||
|
.service(post_add_favorite)
|
||||||
})
|
})
|
||||||
.bind(dotenv::var("BIND_URL").unwrap())?
|
.bind(dotenv::var("BIND_URL").unwrap())?
|
||||||
.bind("localhost:8088")?
|
.bind("localhost:8088")?
|
||||||
|
|||||||
Reference in New Issue
Block a user