diff --git a/.vscode/settings.json b/.vscode/settings.json index 4404ff9..7fc20b6 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,4 +13,5 @@ "./crates/core_photos/Cargo.toml" ], "rust-analyzer.showUnlinkedFileNotification": false, + "debug.allowBreakpointsEverywhere": true } diff --git a/CHANGELOG.md b/CHANGELOG.md index 80a1021..c87c607 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## [0.6.0] - 2023-03-26 +## [Unreleased] ### Changed - Rust rewrite - License changed to AGPL @@ -51,7 +51,7 @@ - async file logging -[0.6.0]: https://github.com/photos-network/core/compare/Release/v0.5.1...Release/v0.6.0 +[unreleased]: https://github.com/photos-network/core/compare/Release/v0.5.1...HEAD [0.5.1]: https://github.com/photos-network/core/compare/Release/v0.5.0...Release/v0.5.1 [0.5.0]: https://github.com/photos-network/core/compare/Release/v0.4.0...Release/v0.5.0 [0.4.0]: https://github.com/photos-network/core/compare/Release/v0.3.0...Release/v0.4.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..988eafb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,102 @@ +# Welcome to Photos.network + +This is a **FOSS** (free and open-source software) and lives from contributions of the community. + +There are many ways to contribute: + + * 📣 Spread the project or its apps to the world + * ✍️ Writing tutorials and blog posts + * 📝 Create or update the documentation + * 🐛 Submit bug reports + * 💡 Adding ideas and feature requests to Discussions + * 👩‍🎨 Create designs or UX flows + * 🧑‍💻 Contribute code or review PRs + + + +## 📜 Ground Rules + +A community like this should be **open**, **considerate** and **respectful**. + +Behaviours that reinforce these values contribute to a positive environment, and include: + + * **Being open**. Members of the community are open to collaboration, whether it's on PEPs, patches, problems, or otherwise. + * **Focusing on what is best for the community**. We're respectful of the processes set forth in the community, and we work within them. + * **Acknowledging time and effort**. We're respectful of the volunteer efforts that permeate the Python community. We're thoughtful when addressing the efforts of others, keeping in mind that often times the labor was completed simply for the good of the community. + * **Being respectful of differing viewpoints and experiences**. We're receptive to constructive comments and criticism, as the experiences and skill sets of other members contribute to the whole of our efforts. + * **Showing empathy towards other community members**. We're attentive in our communications, whether in person or online, and we're tactful when approaching differing views. + * **Being considerate**. Members of the community are considerate of their peers -- other Python users. + * **Being respectful**. We're respectful of others, their positions, their skills, their commitments, and their efforts. + * **Gracefully accepting constructive criticism**. When we disagree, we are courteous in raising our issues. + * **Using welcoming and inclusive language**. We're accepting of all who wish to take part in our activities, fostering an environment where anyone can participate and everyone can make a difference. + + + +## 🧑‍💻 Code Contribution + +To contribute code to the repository, you don't need any permissions. +First start by forking the repository, clone and checkout your clone and start coding. +When you're happy with your changes, create Atomic commits on a **new feature branch** and push it to ***your*** fork. + +Atomic commits will make it easier to track down regressions. Also, it enables the ability to cherry-pick or revert a change if needed. + +1. Fork it (https://github.com/photos-network/core/fork) +2. Create a new feature branch (`git checkout -b feature/fooBar`) +3. Commit your changes (`git commit -am 'Add some fooBar'`) +4. Push to the branch (`git push origin feature/fooBar`) +5. Create a new Pull Request + + + +## 🐛 How to report a bug + +> If you find a security vulnerability, do NOT open an issue. Email [benjamin@stuermer.pro] instead. + +1. Open the [issues tab](https://github.com/photos-network/core/issues) on github +2. Click on [New issue](https://github.com/photos-network/core/issues/new/choose) +3. Choose the bug report 🐛 template and fill out all required fields + + + +## 💡 How to suggest a feature or enhancement + +Check [open issues](https://github.com/photos-network/core/issues) for a list of proposed features. + +If your suggestion can not be found already, see if it is already covered by our [Roadmap](https://github.com/photos-network/core/#roadmap). + + + +## 📟 Communication + +To get in touch with the community join our [Discord](https://img.shields.io/discord/793235453871390720) or write use on Mastodon: [@photos@mastodon.cloud](https://mastodon.cloud/@photos). + + + +## 💾 Technology + +The project is written in [Rust](https://rust-lang.org/) + +Underneath it is using these frameworks: + +* [tokio](https://github.com/tokio-rs/tokio) - an asynchronous runtime +* [tower](https://github.com/tower-rs/tower) - for networking +* [axum](https://github.com/tokio-rs/axum) - as web framework +* [abi_stable](https://github.com/rodrimati1992/abi_stable_crates) - FFI for dynamic library loading + + + +## 💻 Build & Run + +To build and run the core + +```shell +$ cargo run +``` + +### 🔬 Verifications + +To run tests + +```shell +$ cargo test +``` diff --git a/README.md b/README.md index 70d5d23..d5004e7 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,19 @@ The core is written in [Rust](https://rust-lang.org/) and highly customizably by +### Roadmap (MvP) + + - Authenticate (either via openID or fediverse identity) + - Manage photos (upload, download, delete) + - Metadata (size, resolution) + - *EXIF (orientation, image taken timestamp, last modified, camera) + - *RAW (image support for RAW-images) + - *Resize (create low-resolutions / thumbnails) + - *Deep learning (image recognition, Reinforcement learning) + - *Plugin System (extract features into plugins) + + + ### Visual Studio Code The fastest start into development can be archived by using [Visual Studio Code](https://code.visualstudio.com/) and [Docker](https://www.docker.com/get-started). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..2eb2cef --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,20 @@ +# Security + +We take the security of this software seriously. + +If you believe you have found a security vulnerability in any of our repositories, please report it to us as described below. + + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, send email at [security@photos.network](mailto:security@photos.network). +If possible, encrypt your message with our PGP key; +- **Fingerprint**: C320 7E30 54CD AA7B E197  DFF4 1B42 5A06 30A6 ABD0 +- **Public key**: https://keys.openpgp.org/search?q=security@photos.network + + +Please do not make vulnerabilities public without notifying us and giving us at least 4 weeks to respond. + +If you are going to write about Photos.network’s security, please get in touch, so we can make sure that all claims are correct. diff --git a/crates/core_activity_pub/src/lib.rs b/crates/core_activity_pub/src/lib.rs index d21895c..1c2d421 100644 --- a/crates/core_activity_pub/src/lib.rs +++ b/crates/core_activity_pub/src/lib.rs @@ -1,20 +1,18 @@ /* Photos.network · A privacy first photo storage and sharing service for fediverse. * Copyright (C) 2020 Photos network developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ - use activitypub_federation::config::{Data, UrlVerifier}; - diff --git a/crates/core_common/src/model/sensitive.rs b/crates/core_common/src/model/sensitive.rs index c397e23..5eb8013 100644 --- a/crates/core_common/src/model/sensitive.rs +++ b/crates/core_common/src/model/sensitive.rs @@ -1,16 +1,16 @@ /* Photos.network · A privacy first photo storage and sharing service for fediverse. * Copyright (C) 2020 Photos network developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -19,11 +19,11 @@ //! //! Provides an abstraction over a vlue for sensitive data like passwords. //! It is not printing its value to logs or tracing -//! +//! use serde::{Deserialize, Serialize}; use std::{ - borrow::Borrow, - ops::{Deref, DerefMut}, + borrow::Borrow, + ops::{Deref, DerefMut}, }; #[cfg(feature = "full")] use ts_rs::TS; @@ -33,128 +33,126 @@ use ts_rs::TS; pub struct Sensitive(T); impl Sensitive { - pub fn new(item: T) -> Self { - Sensitive(item) - } - pub fn into_inner(self) -> T { - self.0 - } + pub fn new(item: T) -> Self { + Sensitive(item) + } + pub fn into_inner(self) -> T { + self.0 + } } ///! overrides the standard debug programmer-facing representation to prevent the value from leaking. impl std::fmt::Debug for Sensitive { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("[********]").finish() - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("[********]").finish() + } } impl AsRef for Sensitive { - fn as_ref(&self) -> &T { - &self.0 - } + fn as_ref(&self) -> &T { + &self.0 + } } impl AsRef for Sensitive { - fn as_ref(&self) -> &str { - &self.0 - } + fn as_ref(&self) -> &str { + &self.0 + } } impl AsRef<[u8]> for Sensitive { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } } impl AsRef<[u8]> for Sensitive> { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } } impl AsMut for Sensitive { - fn as_mut(&mut self) -> &mut T { - &mut self.0 - } + fn as_mut(&mut self) -> &mut T { + &mut self.0 + } } impl AsMut for Sensitive { - fn as_mut(&mut self) -> &mut str { - &mut self.0 - } + fn as_mut(&mut self) -> &mut str { + &mut self.0 + } } impl Deref for Sensitive { - type Target = str; + type Target = str; - fn deref(&self) -> &Self::Target { - &self.0 - } + fn deref(&self) -> &Self::Target { + &self.0 + } } impl DerefMut for Sensitive { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } impl From for Sensitive { - fn from(t: T) -> Self { - Sensitive(t) - } + fn from(t: T) -> Self { + Sensitive(t) + } } impl From<&str> for Sensitive { - fn from(s: &str) -> Self { - Sensitive(s.into()) - } + fn from(s: &str) -> Self { + Sensitive(s.into()) + } } impl Borrow for Sensitive { - fn borrow(&self) -> &T { - &self.0 - } + fn borrow(&self) -> &T { + &self.0 + } } impl Borrow for Sensitive { - fn borrow(&self) -> &str { - &self.0 - } + fn borrow(&self) -> &str { + &self.0 + } } #[cfg(feature = "full")] impl TS for Sensitive { - fn name() -> String { - "string".to_string() - } - fn name_with_type_args(_args: Vec) -> String { - "string".to_string() - } - fn dependencies() -> Vec { - Vec::new() - } - fn transparent() -> bool { - true - } + fn name() -> String { + "string".to_string() + } + fn name_with_type_args(_args: Vec) -> String { + "string".to_string() + } + fn dependencies() -> Vec { + Vec::new() + } + fn transparent() -> bool { + true + } } - #[cfg(test)] mod tests { - use super::*; - - #[test] - fn debug_representation_should_replace_value() { - let sensitive_secret: Sensitive = "secret".into(); + use super::*; - assert_eq!("[********]", format!("{:?}", sensitive_secret)) - } + #[test] + fn debug_representation_should_replace_value() { + let sensitive_secret: Sensitive = "secret".into(); + assert_eq!("[********]", format!("{:?}", sensitive_secret)) + } - #[test] - fn convert_string_into_should_succeed() { - let sensitive_secret: Sensitive = "secret".into(); + #[test] + fn convert_string_into_should_succeed() { + let sensitive_secret: Sensitive = "secret".into(); - assert_eq!("secret", sensitive_secret.0) - } + assert_eq!("secret", sensitive_secret.0) + } } diff --git a/crates/core_photos/src/lib.rs b/crates/core_photos/src/lib.rs index 89f2c8f..cdd7b04 100644 --- a/crates/core_photos/src/lib.rs +++ b/crates/core_photos/src/lib.rs @@ -1,4 +1,20 @@ +/* Photos.network · A privacy first photo storage and sharing service for fediverse. + * Copyright (C) 2020 Photos network developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + pub mod data { pub mod error; } - diff --git a/crates/core_photos/src/repository/mod.rs b/crates/core_photos/src/repository/mod.rs index 5980fb5..0c3cc17 100644 --- a/crates/core_photos/src/repository/mod.rs +++ b/crates/core_photos/src/repository/mod.rs @@ -1,3 +1,19 @@ +/* Photos.network · A privacy first photo storage and sharing service for fediverse. + * Copyright (C) 2020 Photos network developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ /// MockPhotosRepositoryTrait is created by automock macro #[cfg_attr(test, automock)] diff --git a/src/api/authentication/mod.rs b/src/api/authentication/mod.rs index 9fea63d..579fc9f 100644 --- a/src/api/authentication/mod.rs +++ b/src/api/authentication/mod.rs @@ -1,5 +1,5 @@ use axum::{ - routing::{ get, post }, + routing::{get, post}, Router, }; @@ -15,9 +15,7 @@ use requests::authorization_requests::authorization_endpoint_get; * Autentication Manager is handling access requests via OAuth * by validating the identity of users. */ -pub(crate) struct AutenticationManager { - -} +pub(crate) struct AutenticationManager {} impl AutenticationManager { pub fn routes() -> Router @@ -26,10 +24,9 @@ impl AutenticationManager { { Router::new() .route("/authorize", get(authorization_endpoint_get)) - - .route("/token", post( || async { "Access token request" } )) - .route("/refresh", post( || async { "Access token request" } )) - .route("/", post( || async { "Access token request" } )) + .route("/token", post(|| async { "Access token request" })) + .route("/refresh", post(|| async { "Access token request" })) + .route("/", post(|| async { "Access token request" })) } } diff --git a/src/api/authentication/requests/authorization_requests.rs b/src/api/authentication/requests/authorization_requests.rs index 3ea2c42..ede6374 100644 --- a/src/api/authentication/requests/authorization_requests.rs +++ b/src/api/authentication/requests/authorization_requests.rs @@ -1,15 +1,17 @@ use abi_stable::std_types::string; -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use tracing::debug; - use axum::{ - http::{StatusCode, Uri, header::{self, HeaderMap, HeaderName}}, extract::{FromRef, Query, State}, + http::{ + header::{self, HeaderMap, HeaderName}, + StatusCode, Uri, + }, response::IntoResponse, routing::{get, post}, - Router, Json, + Json, Router, }; use oxide_auth_axum::{OAuthRequest, OAuthResponse, WebError}; @@ -26,22 +28,28 @@ pub async fn authorization_endpoint_get() -> impl IntoResponse { debug!("GET /oauth/authorize from "); // TODO: change return - let error = Error { message: String::from("Not implemented!") }; + let error = Error { + message: String::from("Not implemented!"), + }; ( - StatusCode::FOUND, - [ - (header::LOCATION, "https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz") - ], - Json(error) + StatusCode::FOUND, + [( + header::LOCATION, + "https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz", + )], + Json(error), ) } #[cfg(test)] mod tests { use crate::api::authentication::AutenticationManager; - use axum::{http::{Request, StatusCode, header, self}, body::Body}; - use tower::ServiceExt; + use axum::{ + body::Body, + http::{self, header, Request, StatusCode}, + }; use serde::{Deserialize, Serialize}; + use tower::ServiceExt; #[derive(Serialize, Deserialize, Debug)] pub struct AuthorizationRequest { @@ -60,15 +68,14 @@ mod tests { async fn valid_authorization_should_be_validated_and_redirected() { // given let router = AutenticationManager::routes(); - let form_data = serde_urlencoded::to_string( - AuthorizationRequest { - response_type: String::from("code"), - client_id: String::from("1234"), - redirect_uri: None,//Some(vec!(String::from("https://client.example.com/cb"))), - scope: Some(String::from("s6BhdRkqt3")), - state: Some(String::from("xyz")), - } - ).expect("parse authorization request failed!"); + let form_data = serde_urlencoded::to_string(AuthorizationRequest { + response_type: String::from("code"), + client_id: String::from("1234"), + redirect_uri: None, //Some(vec!(String::from("https://client.example.com/cb"))), + scope: Some(String::from("s6BhdRkqt3")), + state: Some(String::from("xyz")), + }) + .expect("parse authorization request failed!"); // when let response = router @@ -76,7 +83,10 @@ mod tests { Request::builder() .method(http::Method::GET) .uri("/authorize") - .header(http::header::CONTENT_TYPE, "application/x-www-form-urlencode") + .header( + http::header::CONTENT_TYPE, + "application/x-www-form-urlencode", + ) .body(Body::from(form_data)) .unwrap(), ) diff --git a/src/lib.rs b/src/lib.rs index aaa5ea1..708c0b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,40 +1,37 @@ /* Photos.network · A privacy first photo storage and sharing service for fediverse. * Copyright (C) 2020 Photos network developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ //! This is the main entry point of the Photos.network core application. //! -use std::fs; use std::collections::HashMap; +use std::fs; use std::net::SocketAddr; use abi_stable::external_types::crossbeam_channel; -use abi_stable::std_types::RResult::{ROk, RErr}; +use abi_stable::std_types::RResult::{RErr, ROk}; use anyhow::Result; -use axum::{Json, Router}; use axum::routing::{get, head}; +use axum::{Json, Router}; use photos_network_plugin::{PluginFactory_Ref, PluginId}; use serde::{Deserialize, Serialize}; use tower_http::services::ServeDir; use tower_http::trace::TraceLayer; -use tracing::{info, error}; -use tracing_subscriber::{ - fmt, - layer::SubscriberExt, -}; +use tracing::{error, info}; +use tracing_subscriber::{fmt, layer::SubscriberExt}; use config::Configuration; use plugin::plugin_manager::PluginManager; @@ -45,12 +42,10 @@ pub mod api { pub mod authentication; } - const CONFIG_PATH: &str = "./config/configuration.json"; const PLUGIN_PATH: &str = "./plugins"; const LOGGING_PATH: &str = "./logs"; - /// extract the server start into lib.rs for better testability pub async fn start_server() -> Result<()> { // enable logging @@ -63,8 +58,13 @@ pub async fn start_server() -> Result<()> { .with_target(false) .finish() // add additional writers - .with(fmt::Layer::default().with_ansi(false).with_writer(file_writer)) - ).expect("Unable to set global tracing subscriber"); + .with( + fmt::Layer::default() + .with_ansi(false) + .with_writer(file_writer), + ), + ) + .expect("Unable to set global tracing subscriber"); info!("Photos.network core is starting..."); @@ -78,8 +78,6 @@ pub async fn start_server() -> Result<()> { // init application state let mut app_state = ApplicationState::new(config.clone()); - - let mut router = Router::new() // favicon .nest_service("/assets", ServeDir::new("src/api/static")) @@ -89,30 +87,25 @@ pub async fn start_server() -> Result<()> { // oauth 2 .nest("/oauth", api::authentication::AutenticationManager::routes()) .layer(TraceLayer::new_for_http()) - + // TODO: share app state with routes // .with_state(Arc::new(app_state)) ; app_state.router = Some(router); - - - let mut plugin_manager = PluginManager::new( - config.clone(), - PLUGIN_PATH.to_string(), - &mut app_state - )?; + let mut plugin_manager = + PluginManager::new(config.clone(), PLUGIN_PATH.to_string(), &mut app_state)?; match plugin_manager.init().await { Ok(_) => info!("PluginManager: initialization succed."), - Err(e) => error!("PluginManager: initialization failed! {}", e) + Err(e) => error!("PluginManager: initialization failed! {}", e), } plugin_manager.trigger_on_init().await; // trigger `on_core_init` on all loaded plugins for (plugin_id, factory) in app_state.plugins { info!("plugin {} found in AppState.", plugin_id); - + let plugin_constructor = factory.new(); let (sender, _receiver) = crossbeam_channel::unbounded(); @@ -121,7 +114,10 @@ pub async fn start_server() -> Result<()> { ROk(x) => x, RErr(_) => { // TODO: handle error - error!("Not able to trigger plugin constructor for '{}'!", plugin_id); + error!( + "Not able to trigger plugin constructor for '{}'!", + plugin_id + ); //plugin_new_errs.push((plugin_id.clone(), e)); continue; } @@ -129,10 +125,12 @@ pub async fn start_server() -> Result<()> { plugin.on_core_init(); } - + // TODO: add routes lazy (e.g. from plugin) - router = app_state.router.unwrap().route("/test", get( || async { "Test from within plugin" } )); - + router = app_state + .router + .unwrap() + .route("/test", get(|| async { "Test from within plugin" })); // start server with all routes let addr: SocketAddr = SocketAddr::from(([0, 0, 0, 0], 7777)); @@ -145,7 +143,6 @@ pub async fn start_server() -> Result<()> { Ok(()) } - pub struct ApplicationState { pub config: Configuration, pub plugins: HashMap, @@ -162,12 +159,13 @@ impl ApplicationState { } } - async fn status() -> Json { // TODO: get app state // TODO: print loaded plugins from appState - let status = Status { message: String::from("API running") }; + let status = Status { + message: String::from("API running"), + }; Json(status) } diff --git a/src/main.rs b/src/main.rs index 141a454..d3c7813 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,16 +1,16 @@ /* Photos.network · A privacy first photo storage and sharing service for fediverse. * Copyright (C) 2020 Photos network developers - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ diff --git a/src/plugin/plugin_manager.rs b/src/plugin/plugin_manager.rs index 9fd346c..ba760ef 100644 --- a/src/plugin/plugin_manager.rs +++ b/src/plugin/plugin_manager.rs @@ -1,16 +1,13 @@ +use std::path::PathBuf; -use std::path::{PathBuf}; - -use abi_stable::{ - library::{lib_header_from_path, LibrarySuffix, RawLibrary}, -}; +use abi_stable::library::{lib_header_from_path, LibrarySuffix, RawLibrary}; use anyhow::Result; +use crate::{config::Configuration, ApplicationState}; use core_extensions::SelfOps; use photos_network_plugin::{PluginFactory_Ref, PluginId}; -use tracing::{debug, info, error}; -use crate::{config::{Configuration}, ApplicationState}; +use tracing::{debug, error, info}; pub struct PluginManager<'a> { config: Configuration, @@ -19,22 +16,40 @@ pub struct PluginManager<'a> { } impl<'a> PluginManager<'a> { - pub fn new(config: Configuration, path: String, state: &'a mut ApplicationState) -> Result { - Ok(Self { config, path, state }) + pub fn new( + config: Configuration, + path: String, + state: &'a mut ApplicationState, + ) -> Result { + Ok(Self { + config, + path, + state, + }) } - pub async fn init<'b>(&mut self) -> Result<()> { - info!("Found {} plugin(s) in the configuration.", self.config.plugins.len()); + pub async fn init<'b>(&mut self) -> Result<()> { + info!( + "Found {} plugin(s) in the configuration.", + self.config.plugins.len() + ); for configured_plugin in &self.config.plugins { - info!("Addon '{}' found in the configuration", configured_plugin.plugin_domain()); + info!( + "Addon '{}' found in the configuration", + configured_plugin.plugin_domain() + ); let base_name = configured_plugin.plugin_domain().clone(); let plugin_dir: PathBuf = self.path.clone().into_::(); - let plugin_path: PathBuf = RawLibrary::path_in_directory(&plugin_dir, &base_name, LibrarySuffix::NoSuffix); + let plugin_path: PathBuf = + RawLibrary::path_in_directory(&plugin_dir, &base_name, LibrarySuffix::NoSuffix); if plugin_path.exists() { - debug!("Addon '{}' also found in the `plugins` directory", configured_plugin.plugin_domain()); + debug!( + "Addon '{}' also found in the `plugins` directory", + configured_plugin.plugin_domain() + ); debug!("Try to load plugin..."); let header = lib_header_from_path(&plugin_path)?; @@ -47,10 +62,12 @@ impl<'a> PluginManager<'a> { continue; } }; - - let mut loaded_libraries = Vec::::new(); + + let mut loaded_libraries = Vec::::new(); loaded_libraries.push(PluginId::from(base_name.clone())); - self.state.plugins.insert(PluginId::from(base_name), root_module); + self.state + .plugins + .insert(PluginId::from(base_name), root_module); } }