feature/tagging #16

Merged
cameron merged 22 commits from feature/tagging into master 2023-04-10 12:55:28 +00:00
4 changed files with 43 additions and 52 deletions
Showing only changes of commit ae2642a544 - Show all commits

View File

@@ -2,7 +2,7 @@ use crate::database::schema::{favorites, users};
use serde::Serialize; use serde::Serialize;
#[derive(Insertable)] #[derive(Insertable)]
#[table_name = "users"] #[diesel(table_name = users)]
pub struct InsertUser<'a> { pub struct InsertUser<'a> {
pub username: &'a str, pub username: &'a str,
pub password: &'a str, pub password: &'a str,
@@ -17,7 +17,7 @@ pub struct User {
} }
#[derive(Insertable)] #[derive(Insertable)]
#[table_name = "favorites"] #[diesel(table_name = favorites)]
pub struct InsertFavorite<'a> { pub struct InsertFavorite<'a> {
pub userid: &'a i32, pub userid: &'a i32,
pub path: &'a str, pub path: &'a str,

View File

@@ -184,13 +184,8 @@ impl FileSystemAccess for RealFileSystem {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::database::connect;
use crate::tags::SqliteTagDao;
use actix_web::web::Data;
use diesel::{Connection, SqliteConnection};
use std::collections::HashMap; use std::collections::HashMap;
use std::env; use std::env;
use std::ffi::OsStr;
use std::fs::File; use std::fs::File;
use super::*; use super::*;
@@ -342,7 +337,7 @@ mod tests {
let mut tag_dao = SqliteTagDao::new(in_memory_db_connection()); let mut tag_dao = SqliteTagDao::new(in_memory_db_connection());
let tag1 = tag_dao.create_tag("tag1").unwrap(); let tag1 = tag_dao.create_tag("tag1").unwrap();
let tag2 = tag_dao.create_tag("tag2").unwrap(); let _tag2 = tag_dao.create_tag("tag2").unwrap();
let tag3 = tag_dao.create_tag("tag3").unwrap(); let tag3 = tag_dao.create_tag("tag3").unwrap();
let _ = &tag_dao.tag_file("test.jpg", tag1.id).unwrap(); let _ = &tag_dao.tag_file("test.jpg", tag1.id).unwrap();
@@ -409,8 +404,11 @@ mod tests {
], ],
); );
let request: Query<FilesRequest> = let request: Query<FilesRequest> = Query::from_query(&*format!(
Query::from_query("path=&tag_ids=1,3&tag_filter_mode=All").unwrap(); "path=&tag_ids={},{}&tag_filter_mode=All",
tag1.id, tag3.id
))
.unwrap();
let response: HttpResponse = list_photos( let response: HttpResponse = list_photos(
claims, claims,

View File

@@ -216,7 +216,8 @@ async fn stream_video(
debug!("Playlist: {}", playlist); debug!("Playlist: {}", playlist);
// Extract video playlist dir to dotenv // Extract video playlist dir to dotenv
if !playlist.starts_with("tmp") && is_valid_full_path(&app_state.base_path, playlist).is_some() { if !playlist.starts_with("tmp") && is_valid_full_path(&app_state.base_path, playlist).is_some()
{
HttpResponse::BadRequest().finish() HttpResponse::BadRequest().finish()
} else if let Ok(file) = NamedFile::open(playlist) { } else if let Ok(file) = NamedFile::open(playlist) {
file.into_response(&request) file.into_response(&request)
@@ -354,16 +355,14 @@ fn create_thumbnails() {
.filter_map(|entry| entry.ok()) .filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().is_file()) .filter(|entry| entry.file_type().is_file())
.filter(|entry| { .filter(|entry| {
debug!("{:?}", entry.path()); if is_video(entry) {
if let Some(ext) = entry
.path()
.extension()
.and_then(|ext| ext.to_str().map(|ext| ext.to_lowercase()))
{
if ext == "mp4" || ext == "mov" {
let relative_path = &entry.path().strip_prefix(&images).unwrap(); let relative_path = &entry.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);
std::fs::create_dir_all(thumb_path.parent().unwrap_or_else(|| panic!("Thumbnail {:?} has no parent?", thumb_path))) std::fs::create_dir_all(
thumb_path
.parent()
.unwrap_or_else(|| panic!("Thumbnail {:?} has no parent?", thumb_path)),
)
.expect("Error creating directory"); .expect("Error creating directory");
debug!("Generating video thumbnail: {:?}", thumb_path); debug!("Generating video thumbnail: {:?}", thumb_path);
@@ -372,10 +371,6 @@ fn create_thumbnails() {
} else { } else {
is_image(entry) is_image(entry)
} }
} else {
error!("Unable to get extension for file: {:?}", entry.path());
false
}
}) })
.filter(|entry| { .filter(|entry| {
let path = entry.path(); let path = entry.path();
@@ -490,7 +485,9 @@ fn main() -> std::io::Result<()> {
.service(get_file_metadata) .service(get_file_metadata)
.add_feature(add_tag_services::<_, SqliteTagDao>) .add_feature(add_tag_services::<_, SqliteTagDao>)
.app_data(app_data.clone()) .app_data(app_data.clone())
.app_data::<Data<RealFileSystem>>(Data::new(RealFileSystem::new(app_data.base_path.clone()))) .app_data::<Data<RealFileSystem>>(Data::new(RealFileSystem::new(
app_data.base_path.clone(),
)))
.app_data::<Data<Mutex<SqliteUserDao>>>(Data::new(Mutex::new(user_dao))) .app_data::<Data<Mutex<SqliteUserDao>>>(Data::new(Mutex::new(user_dao)))
.app_data::<Data<Mutex<Box<dyn FavoriteDao>>>>(Data::new(Mutex::new(Box::new( .app_data::<Data<Mutex<Box<dyn FavoriteDao>>>>(Data::new(Mutex::new(Box::new(
favorites_dao, favorites_dao,

View File

@@ -92,8 +92,7 @@ async fn update_tags<D: TagDao>(
) -> impl Responder { ) -> impl Responder {
let mut dao = tag_dao.lock().expect("Unable to get TagDao"); let mut dao = tag_dao.lock().expect("Unable to get TagDao");
dao dao.get_tags_for_path(&request.file_name)
.get_tags_for_path(&request.file_name)
.and_then(|existing_tags| dao.get_all_tags().map(|all| (existing_tags, all))) .and_then(|existing_tags| dao.get_all_tags().map(|all| (existing_tags, all)))
.map(|(existing_tags, all_tags)| { .map(|(existing_tags, all_tags)| {
let tags_to_remove = existing_tags let tags_to_remove = existing_tags
@@ -144,14 +143,14 @@ pub struct Tag {
} }
#[derive(Insertable, Clone, Debug)] #[derive(Insertable, Clone, Debug)]
#[table_name = "tags"] #[diesel(table_name = tags)]
pub struct InsertTag { pub struct InsertTag {
pub name: String, pub name: String,
pub created_time: i64, pub created_time: i64,
} }
#[derive(Insertable, Clone, Debug)] #[derive(Insertable, Clone, Debug)]
#[table_name = "tagged_photo"] #[diesel(table_name = tagged_photo)]
pub struct InsertTaggedPhoto { pub struct InsertTaggedPhoto {
pub tag_id: i32, pub tag_id: i32,
pub photo_name: String, pub photo_name: String,
@@ -220,15 +219,13 @@ impl TagDao for SqliteTagDao {
created_time: Utc::now().timestamp(), created_time: Utc::now().timestamp(),
}) })
.execute(&mut self.connection) .execute(&mut self.connection)
.with_context(|| "Unable to insert tag in Sqlite") .with_context(|| format!("Unable to insert tag {:?} in Sqlite", name))
.and_then(|_| { .and_then(|_| {
debug!("Inserted tag: {:?}", name); info!("Inserted tag: {:?}", name);
no_arg_sql_function!( sql_function! {
last_insert_rowid, fn last_insert_rowid() -> diesel::sql_types::Integer;
diesel::sql_types::Integer, }
"Represents the SQL last_insert_row() function" diesel::select(last_insert_rowid())
);
diesel::select(last_insert_rowid)
.get_result::<i32>(&mut self.connection) .get_result::<i32>(&mut self.connection)
.with_context(|| "Unable to get last inserted tag from Sqlite") .with_context(|| "Unable to get last inserted tag from Sqlite")
}) })
@@ -238,7 +235,9 @@ impl TagDao for SqliteTagDao {
.filter(tags::id.eq(id)) .filter(tags::id.eq(id))
.select((tags::id, tags::name, tags::created_time)) .select((tags::id, tags::name, tags::created_time))
.get_result::<Tag>(self.connection.borrow_mut()) .get_result::<Tag>(self.connection.borrow_mut())
.with_context(|| "Unable to get tagged photo from Sqlite") .with_context(|| {
format!("Unable to get tagged photo with id: {:?} from Sqlite", id)
})
}) })
} }
@@ -275,18 +274,15 @@ impl TagDao for SqliteTagDao {
.execute(self.connection.borrow_mut()) .execute(self.connection.borrow_mut())
.with_context(|| format!("Unable to tag file {:?} in sqlite", path)) .with_context(|| format!("Unable to tag file {:?} in sqlite", path))
.and_then(|_| { .and_then(|_| {
debug!("Inserted tagged photo: {:#} -> {:?}", tag_id, path); info!("Inserted tagged photo: {:#} -> {:?}", tag_id, path);
no_arg_sql_function!( sql_function! {
last_insert_rowid, fn last_insert_rowid() -> diesel::sql_types::Integer;
diesel::sql_types::Integer, }
"Represents the SQL last_insert_row() function" diesel::select(last_insert_rowid())
);
diesel::select(last_insert_rowid)
.get_result::<i32>(&mut self.connection) .get_result::<i32>(&mut self.connection)
.with_context(|| "Unable to get last inserted tag from Sqlite") .with_context(|| "Unable to get last inserted tag from Sqlite")
}) })
.and_then(|tagged_id| { .and_then(|tagged_id| {
debug!("Inserted tagged photo: {:?}", tagged_id);
tagged_photo::table tagged_photo::table
.find(tagged_id) .find(tagged_id)
.first(self.connection.borrow_mut()) .first(self.connection.borrow_mut())