diff --git a/Cargo.lock b/Cargo.lock index c3afef5..f7e569f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -777,10 +777,10 @@ dependencies = [ "axum", "core_common", "core_extensions", - "core_photos", "futures", "futures-channel", "futures-util", + "media", "oauth_authentication", "oauth_authorization_server", "photos_network_plugin", @@ -839,13 +839,6 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69f3b219d28b6e3b4ac87bc1fc522e0803ab22e055da177bff0068c4150c61a6" -[[package]] -name = "core_photos" -version = "0.6.0" -dependencies = [ - "serde", -] - [[package]] name = "cpufeatures" version = "0.2.8" @@ -2151,6 +2144,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +[[package]] +name = "media" +version = "0.6.0" +dependencies = [ + "axum", + "serde", + "tower-http", +] + [[package]] name = "memchr" version = "2.5.0" diff --git a/Cargo.toml b/Cargo.toml index 83e2a83..d1d54ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ members = [ "crates/oauth_authorization_server", "crates/oauth_authentication", "crates/core_common", - "crates/core_photos", + "crates/media", "crates/activity_pub", "crates/plugin_interface" ] @@ -37,7 +37,7 @@ members = [ oauth_authorization_server = { path = "./crates/oauth_authorization_server" } oauth_authentication = { path = "./crates/oauth_authentication" } core_common = { path = "./crates/core_common" } -core_photos = { path = "./crates/core_photos" } +media = { path = "./crates/media" } activity_pub = { path = "./crates/activity_pub" } activitypub_federation = "~0.4.0" @@ -80,7 +80,7 @@ oauth_authorization_server = { workspace = true } oauth_authentication = { workspace = true } # core_api = { workspace = true } core_common = { workspace = true } -core_photos = { workspace = true } +media = { workspace = true } activity_pub = { workspace = true } # core_api_crud = { workspace = true } diff --git a/LICENSE.md b/LICENSE.md index f8bf669..c796e17 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -629,7 +629,7 @@ to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. - Photos.network · A privacy first photo storage and sharing service for fediverse. + Photos.network · A privacy first, self-hosted photo storage and sharing service for fediverse. Copyright 2020 Photos network developers This program is free software: you can redistribute it and/or modify diff --git a/README.md b/README.md index d5004e7..572ad1a 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/photos-network/core/check%20code%20quality) -[Photos.network](https://photos.network) is a privacy first photo storage and sharing service for fediverse. +[Photos.network](https://photos.network) is a free and open source, privacy first, self-hosted photo storage and sharing service for fediverse. Its core features are: diff --git a/crates/accounts/router.rs b/crates/accounts/router.rs new file mode 100644 index 0000000..ef5b59a --- /dev/null +++ b/crates/accounts/router.rs @@ -0,0 +1,80 @@ +/* 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 axum::routing::get; +use axum::Router; +use handler::{ + authorize::authorization_handler, + discovery::openid_discover_handler, + jwks::openid_jwks_handler, + login::{get_realm_login_form, post_realm_login}, +}; +use state::ServerState; +use std::sync::{Arc, RwLock}; + +pub mod client; +pub mod config; +pub mod error; +pub mod query; +pub mod realm; +pub mod request; +pub mod state; +pub mod handler { + pub mod authorize; + pub mod discovery; + pub mod jwks; + pub mod login; +} + +pub struct AccountsApi {} + +impl AccountsApi { + pub fn routes() -> Router + where + S: Send + Sync + 'static + Clone, + { + Router::new() + // Returns information about a single account by ID + // 200 OK + // 401 Unauthorized - Requesting user is unauthenticated + // 404 Not Found - The requested resource does not exist. + .route("/users/:user_id/profile", get(list_photos_handler)) + // Update a single account when `admin.users:write` scope is present + // 200 - OK + // 400 Bad Request - The request body was malformed or a field violated its constraints. + // 401 Unauthorized - You are unauthenticated + // 403 Forbidden - You are authenticated but have no permission to manage the target user. + // 404 Not Found - The requested resource does not exist. + .route("/users/:user_id/profile", patch(list_photos_handler)) + + // Disable a single account by ID when `admin.users:write` scope is present + // 204 No Content - Account was disabled successful + // 401 Unauthorized - You are unauthenticated + // 403 Forbidden - You are authenticated but have no permission to manage the target user. + // 404 Not Found - The requested resource does not exist. + .route("/users/:user_id/disable", patch(list_photos_handler)) + + // Enable a single account by ID when `admin.users:write` scope is present + // 204 No Content - Account was enabled successful + // 401 Unauthorized - You are unauthenticated + // 403 Forbidden - You are authenticated but have no permission to manage the target user. + // 404 Not Found - The requested resource does not exist. + .route("/users/:user_id/enabled", patch(list_photos_handler)) + + .layer(tower_http::trace::TraceLayer::new_for_http()) + } +} diff --git a/crates/core_photos/README.md b/crates/core_photos/README.md deleted file mode 100644 index ff76996..0000000 --- a/crates/core_photos/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# core_photos - -This crate provides all photos related layers (data layer, domain, endpoints). diff --git a/crates/core_photos/Cargo.toml b/crates/media/Cargo.toml similarity index 65% rename from crates/core_photos/Cargo.toml rename to crates/media/Cargo.toml index 83dc41f..ded1a06 100644 --- a/crates/core_photos/Cargo.toml +++ b/crates/media/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "core_photos" +name = "media" +description = "Manages all media items in the database and on filesystem." version.workspace = true authors.workspace = true -description.workspace = true homepage.workspace = true documentation.workspace = true repository.workspace = true @@ -11,9 +11,13 @@ license.workspace = true edition.workspace = true [lib] -name = "core_photos" +name = "media" path = "src/lib.rs" doctest = false [dependencies] serde = { workspace = true, features = ["derive"] } + +# Router +axum = { workspace = true } +tower-http.workspace = true diff --git a/crates/media/README.md b/crates/media/README.md new file mode 100644 index 0000000..34cd85b --- /dev/null +++ b/crates/media/README.md @@ -0,0 +1,6 @@ +# media + +This crate handles all media items like photos or albums for [Photos.network](https://photos.network). + +Persisting the metadata in a database with [SQLx](https://crates.io/crates/sqlx) and accessing the files via [filesystem](https://crates.io/crates/filesystem). + diff --git a/crates/media/src/api/handler/file_handler.rs b/crates/media/src/api/handler/file_handler.rs new file mode 100644 index 0000000..759b62a --- /dev/null +++ b/crates/media/src/api/handler/file_handler.rs @@ -0,0 +1,14 @@ +//! Returns the binary of a given entity +//! + +use axum::http::StatusCode; + +pub(crate) async fn file_handler() -> std::result::Result { + // TODO: parse params max-with / max-height =wmax-width-hmax-height (=w2048-h1024) + // -wmax-width (preserving the aspect ratio) + // -hmax-height (preserving the aspect ratio) + // -c crop images to max-width / max-height + // -d remove exif data + + Err(StatusCode::NOT_IMPLEMENTED) +} diff --git a/crates/media/src/api/handler/list_photos_handler.rs b/crates/media/src/api/handler/list_photos_handler.rs new file mode 100644 index 0000000..f172f3a --- /dev/null +++ b/crates/media/src/api/handler/list_photos_handler.rs @@ -0,0 +1,7 @@ +//! Returns a list of media items owned or shared with the user +//! +pub(crate) async fn list_photos_handler( + +) -> std::result::Result { + Err(StatusCode::NOT_IMPLEMENTED) +} diff --git a/crates/media/src/api/handler/photo_details.rs b/crates/media/src/api/handler/photo_details.rs new file mode 100644 index 0000000..f4bce90 --- /dev/null +++ b/crates/media/src/api/handler/photo_details.rs @@ -0,0 +1,7 @@ +//! Returns the details of a given media item +//! +pub(crate) async fn photo_details_handler( + +) -> std::result::Result { + Err(StatusCode::NOT_IMPLEMENTED) +} diff --git a/crates/media/src/api/router.rs b/crates/media/src/api/router.rs new file mode 100644 index 0000000..f47a5ea --- /dev/null +++ b/crates/media/src/api/router.rs @@ -0,0 +1,52 @@ +/* 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 crate::api::handler::file_handler::file_handler; +use axum::routing::{get, patch, post}; +use axum::Router; + +pub struct MediaApi {} + +impl MediaApi { + pub fn routes() -> Router + where + S: Send + Sync + 'static + Clone, + { + Router::new() + // list owned and shared items + .route("/photos", get(file_handler)) + // get metadata of a specific item + .route("/photos/:entity_id", get(file_handler)) + // update the given media item owned by the user + .route("/photos/:entity_id", patch(file_handler)) + // creates one or multiple media items + .route("/photos", post(file_handler)) + // list owned and shared albums + .route("/albums", get(file_handler)) + // create new album + .route("/albums", post(file_handler)) + // get metadata of a specific owned or shared album + .route("/albums/:entity_id", get(file_handler)) + // updates the given album owned by the user + .route("/albums/:entity_id", patch(file_handler)) + // shares the given album + .route("/albums/:entity_id/share", patch(file_handler)) + // unshares the given album + .route("/albums/:entity_id/unshare", patch(file_handler)) + .layer(tower_http::trace::TraceLayer::new_for_http()) + } +} diff --git a/crates/core_photos/src/data/error.rs b/crates/media/src/data/error.rs similarity index 100% rename from crates/core_photos/src/data/error.rs rename to crates/media/src/data/error.rs diff --git a/crates/core_photos/src/data/mod.rs b/crates/media/src/data/mod.rs similarity index 100% rename from crates/core_photos/src/data/mod.rs rename to crates/media/src/data/mod.rs diff --git a/crates/core_photos/src/data/photo.rs b/crates/media/src/data/photo.rs similarity index 100% rename from crates/core_photos/src/data/photo.rs rename to crates/media/src/data/photo.rs diff --git a/crates/core_photos/src/lib.rs b/crates/media/src/lib.rs similarity index 89% rename from crates/core_photos/src/lib.rs rename to crates/media/src/lib.rs index cdd7b04..35d0621 100644 --- a/crates/core_photos/src/lib.rs +++ b/crates/media/src/lib.rs @@ -18,3 +18,10 @@ pub mod data { pub mod error; } + +pub mod api { + pub mod handler { + pub mod file_handler; + } + pub mod router; +} diff --git a/crates/core_photos/src/repository/mod.rs b/crates/media/src/repository/mod.rs similarity index 100% rename from crates/core_photos/src/repository/mod.rs rename to crates/media/src/repository/mod.rs diff --git a/crates/oauth_authentication/src/lib.rs b/crates/oauth_authentication/src/lib.rs index 2f54671..dd6a21c 100644 --- a/crates/oauth_authentication/src/lib.rs +++ b/crates/oauth_authentication/src/lib.rs @@ -15,41 +15,73 @@ * along with this program. If not, see . */ -use openidconnect::{ - AccessTokenHash, - AuthenticationFlow, - AuthorizationCode, - ClientId, - ClientSecret, - CsrfToken, - Nonce, - IssuerUrl, - PkceCodeChallenge, - RedirectUrl, - Scope, ProviderMetadata, EmptyAdditionalProviderMetadata, PkceCodeVerifier, -}; +use anyhow::{anyhow, Ok}; use openidconnect::core::{ - CoreAuthenticationFlow, - CoreClient, - CoreProviderMetadata, - CoreResponseType, - CoreUserInfoClaims, + CoreAuthenticationFlow, CoreClient, CoreProviderMetadata, CoreResponseType, CoreUserInfoClaims, +}; +use openidconnect::{ + AccessTokenHash, AuthorizationCode, ClientId, ClientSecret, CsrfToken, + EmptyAdditionalProviderMetadata, IssuerUrl, Nonce, PkceCodeChallenge, PkceCodeVerifier, + ProviderMetadata, RedirectUrl, Scope, }; -use anyhow::{anyhow, Ok}; -use openidconnect::reqwest::http_client; -use url::Url; use anyhow::Result; +use openidconnect::reqwest::http_client; use thiserror::Error; // Use OpenID Connect Discovery to fetch the provider metadata. use openidconnect::{OAuth2TokenResponse, TokenResponse}; pub struct AuthenticationManager { - pub client : openidconnect::Client, openidconnect::StandardTokenResponse, openidconnect::core::CoreTokenType>, openidconnect::core::CoreTokenType, openidconnect::StandardTokenIntrospectionResponse, openidconnect::core::CoreRevocableToken, openidconnect::StandardErrorResponse>, - pub provider_metadata: ProviderMetadata, + pub client: openidconnect::Client< + openidconnect::EmptyAdditionalClaims, + openidconnect::core::CoreAuthDisplay, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + openidconnect::core::CoreJsonWebKeyUse, + openidconnect::core::CoreJsonWebKey, + openidconnect::core::CoreAuthPrompt, + openidconnect::StandardErrorResponse, + openidconnect::StandardTokenResponse< + openidconnect::IdTokenFields< + openidconnect::EmptyAdditionalClaims, + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + >, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreTokenType, + openidconnect::StandardTokenIntrospectionResponse< + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreRevocableToken, + openidconnect::StandardErrorResponse, + >, + pub provider_metadata: ProviderMetadata< + EmptyAdditionalProviderMetadata, + openidconnect::core::CoreAuthDisplay, + openidconnect::core::CoreClientAuthMethod, + openidconnect::core::CoreClaimName, + openidconnect::core::CoreClaimType, + openidconnect::core::CoreGrantType, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJweKeyManagementAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + openidconnect::core::CoreJsonWebKeyUse, + openidconnect::core::CoreJsonWebKey, + openidconnect::core::CoreResponseMode, + CoreResponseType, + openidconnect::core::CoreSubjectIdentifierType, + >, pub pkce_challenge: PkceCodeChallenge, - pub pkce_verifier: PkceCodeVerifier + pub pkce_verifier: PkceCodeVerifier, } #[derive(Debug, Error)] @@ -59,7 +91,6 @@ enum AuthError { } impl AuthenticationManager { - pub fn new() -> Result { tracing::error!("run setup"); @@ -69,27 +100,59 @@ impl AuthenticationManager { )?; // Generate a PKCE challenge. - let ( - pkce_challenge, - pkce_verifier - ): (PkceCodeChallenge, openidconnect::PkceCodeVerifier) = PkceCodeChallenge::new_random_sha256(); - + let (pkce_challenge, pkce_verifier): (PkceCodeChallenge, openidconnect::PkceCodeVerifier) = + PkceCodeChallenge::new_random_sha256(); + Ok(Self { provider_metadata: foo.clone(), client: CoreClient::from_provider_metadata( foo, - ClientId::new("953760225864-77il4losuech1dtsea36tmma2e8bko3h.apps.googleusercontent.com".to_string()), - Some(ClientSecret::new("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".to_string())), + ClientId::new( + "953760225864-77il4losuech1dtsea36tmma2e8bko3h.apps.googleusercontent.com" + .to_string(), + ), + Some(ClientSecret::new( + "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".to_string(), + )), ) // Set the URL the user will be redirected to after the authorization process. .set_redirect_uri(RedirectUrl::new("http://127.0.0.1/callback".to_string())?), - pkce_challenge: pkce_challenge, - pkce_verifier: pkce_verifier + pkce_challenge, + pkce_verifier, }) } pub fn create_authorization_url( - client : openidconnect::Client, openidconnect::StandardTokenResponse, openidconnect::core::CoreTokenType>, openidconnect::core::CoreTokenType, openidconnect::StandardTokenIntrospectionResponse, openidconnect::core::CoreRevocableToken, openidconnect::StandardErrorResponse>, + client: openidconnect::Client< + openidconnect::EmptyAdditionalClaims, + openidconnect::core::CoreAuthDisplay, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + openidconnect::core::CoreJsonWebKeyUse, + openidconnect::core::CoreJsonWebKey, + openidconnect::core::CoreAuthPrompt, + openidconnect::StandardErrorResponse, + openidconnect::StandardTokenResponse< + openidconnect::IdTokenFields< + openidconnect::EmptyAdditionalClaims, + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + >, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreTokenType, + openidconnect::StandardTokenIntrospectionResponse< + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreRevocableToken, + openidconnect::StandardErrorResponse, + >, pkce_challenge: PkceCodeChallenge, ) -> Result { let nonce = Nonce::new_random; @@ -106,7 +169,7 @@ impl AuthenticationManager { // Set the PKCE code challenge. .set_pkce_challenge(pkce_challenge) .url(); - + // This is the URL you should redirect the user to, in order to trigger the authorization // process. println!("Browse to: {}", auth_url); @@ -115,60 +178,91 @@ impl AuthenticationManager { } pub fn exchange_code( - client : openidconnect::Client, openidconnect::StandardTokenResponse, openidconnect::core::CoreTokenType>, openidconnect::core::CoreTokenType, openidconnect::StandardTokenIntrospectionResponse, openidconnect::core::CoreRevocableToken, openidconnect::StandardErrorResponse>, + client: openidconnect::Client< + openidconnect::EmptyAdditionalClaims, + openidconnect::core::CoreAuthDisplay, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + openidconnect::core::CoreJsonWebKeyUse, + openidconnect::core::CoreJsonWebKey, + openidconnect::core::CoreAuthPrompt, + openidconnect::StandardErrorResponse, + openidconnect::StandardTokenResponse< + openidconnect::IdTokenFields< + openidconnect::EmptyAdditionalClaims, + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreGenderClaim, + openidconnect::core::CoreJweContentEncryptionAlgorithm, + openidconnect::core::CoreJwsSigningAlgorithm, + openidconnect::core::CoreJsonWebKeyType, + >, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreTokenType, + openidconnect::StandardTokenIntrospectionResponse< + openidconnect::EmptyExtraTokenFields, + openidconnect::core::CoreTokenType, + >, + openidconnect::core::CoreRevocableToken, + openidconnect::StandardErrorResponse, + >, pkce_verifier: PkceCodeVerifier, authorization_code: String, - nonce: Nonce + nonce: Nonce, ) -> Result<()> { // Once the user has been redirected to the redirect URL, you'll have access to the // authorization code. For security reasons, your code should verify that the `state` // parameter returned by the server matches `csrf_state`. - + // Now you can exchange it for an access token and ID token. - let token_response = - client - .exchange_code(AuthorizationCode::new(authorization_code)) - // Set the PKCE code verifier. - .set_pkce_verifier(pkce_verifier) - .request(http_client)?; - + let token_response = client + .exchange_code(AuthorizationCode::new(authorization_code)) + // Set the PKCE code verifier. + .set_pkce_verifier(pkce_verifier) + .request(http_client)?; + // Extract the ID token claims after verifying its authenticity and nonce. let id_token = token_response - .id_token() - .ok_or_else(|| anyhow!("Server did not return an ID token"))?; + .id_token() + .ok_or_else(|| anyhow!("Server did not return an ID token"))?; let claims = id_token.claims(&client.id_token_verifier(), &nonce)?; - + // Verify the access token hash to ensure that the access token hasn't been substituted for // another user's. if let Some(expected_access_token_hash) = claims.access_token_hash() { let actual_access_token_hash = AccessTokenHash::from_token( token_response.access_token(), - &id_token.signing_alg()? + &id_token.signing_alg()?, )?; if actual_access_token_hash != *expected_access_token_hash { return Err(anyhow!("Invalid access token")); } } - + // The authenticated user's identity is now available. See the IdTokenClaims struct for a // complete listing of the available claims. println!( "User {} with e-mail address {} has authenticated successfully", claims.subject().as_str(), - claims.email().map(|email| email.as_str()).unwrap_or(""), + claims + .email() + .map(|email| email.as_str()) + .unwrap_or(""), ); - + // If available, we can use the UserInfo endpoint to request additional information. - + // The user_info request uses the AccessToken returned in the token response. To parse custom // claims, use UserInfoClaims directly (with the desired type parameters) rather than using the // CoreUserInfoClaims type alias. let userinfo: CoreUserInfoClaims = client - .user_info(token_response.access_token().to_owned(), None) - .map_err(|err| anyhow!("No user info endpoint: {:?}", err))? - .request(http_client) - .map_err(|err| anyhow!("Failed requesting user info: {:?}", err))?; - + .user_info(token_response.access_token().to_owned(), None) + .map_err(|err| anyhow!("No user info endpoint: {:?}", err))? + .request(http_client) + .map_err(|err| anyhow!("Failed requesting user info: {:?}", err))?; + // See the OAuth2TokenResponse trait for a listing of other available fields such as // access_token() and refresh_token(). diff --git a/crates/oauth_authorization_server/src/handler/authorize.rs b/crates/oauth_authorization_server/src/handler/authorize.rs index 1497541..0f855fd 100644 --- a/crates/oauth_authorization_server/src/handler/authorize.rs +++ b/crates/oauth_authorization_server/src/handler/authorize.rs @@ -44,7 +44,7 @@ pub(crate) async fn authorization_handler( }; for realm in state.write().unwrap().realms.iter_mut() { for client in realm.clients.iter() { - if &client.id == &query.client_id { + if client.id == query.client_id { realm.requests.push(req); let realm_login_url = format!("/{}/login", &realm.name); return Ok(Redirect::to(&realm_login_url)); @@ -53,7 +53,7 @@ pub(crate) async fn authorization_handler( } for client in state.read().unwrap().master_realm.clients.iter() { - if &client.id == &query.client_id { + if client.id == query.client_id { state.write().unwrap().master_realm.requests.push(req); let realm_login_url = format!("/{}/login", &state.read().unwrap().master_realm.name); return Ok(Redirect::to(&realm_login_url)); diff --git a/crates/oauth_authorization_server/src/handler/discovery.rs b/crates/oauth_authorization_server/src/handler/discovery.rs index 982cbe1..7189171 100644 --- a/crates/oauth_authorization_server/src/handler/discovery.rs +++ b/crates/oauth_authorization_server/src/handler/discovery.rs @@ -27,7 +27,7 @@ pub(crate) async fn openid_discover_handler( TypedHeader(host): TypedHeader, ) -> Json { for realm in state.read().unwrap().realms.iter() { - if &realm.domain == host.hostname() { + if realm.domain == host.hostname() { return Json(realm.provider_metadata.clone()); } } diff --git a/crates/oauth_authorization_server/src/handler/jwks.rs b/crates/oauth_authorization_server/src/handler/jwks.rs index b949033..d5a0bfc 100644 --- a/crates/oauth_authorization_server/src/handler/jwks.rs +++ b/crates/oauth_authorization_server/src/handler/jwks.rs @@ -27,7 +27,7 @@ pub(crate) async fn openid_jwks_handler( TypedHeader(host): TypedHeader, ) -> Json { for realm in state.read().unwrap().realms.iter() { - if &realm.domain == host.hostname() { + if realm.domain == host.hostname() { return Json(realm.jwks.clone()); } } diff --git a/crates/oauth_authorization_server/src/lib.rs b/crates/oauth_authorization_server/src/lib.rs index 52f4e50..772c819 100644 --- a/crates/oauth_authorization_server/src/lib.rs +++ b/crates/oauth_authorization_server/src/lib.rs @@ -59,6 +59,6 @@ impl AuthorizationServerManager { get(get_realm_login_form).post(post_realm_login), ) .layer(tower_http::trace::TraceLayer::new_for_http()) - .with_state(Arc::new(RwLock::new(server.clone()))) + .with_state(Arc::new(RwLock::new(server))) } } diff --git a/crates/oauth_authorization_server/tests/common/mod.rs b/crates/oauth_authorization_server/tests/common/mod.rs index 3d349bd..cd25f45 100644 --- a/crates/oauth_authorization_server/tests/common/mod.rs +++ b/crates/oauth_authorization_server/tests/common/mod.rs @@ -17,8 +17,10 @@ //! Create a private key file to use for OIDC. //! -use oauth_authorization_server::{config::ServerConfig, state::ServerState, AuthorizationServerManager}; use axum::Router; +use oauth_authorization_server::{ + config::ServerConfig, state::ServerState, AuthorizationServerManager, +}; use rand::rngs::OsRng; use rsa::pkcs1::EncodeRsaPrivateKey; use rsa::pkcs8::LineEnding; diff --git a/src/lib.rs b/src/lib.rs index 3c2ea87..970846f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,17 +24,16 @@ use std::net::SocketAddr; use abi_stable::external_types::crossbeam_channel; use abi_stable::std_types::RResult::{RErr, ROk}; use anyhow::Result; -use oauth_authentication::AuthenticationManager; +use axum::routing::{get, head}; +use axum::{Json, Router}; +use media::api::router::MediaApi; use oauth_authorization_server::client::Client; use oauth_authorization_server::config::ConfigRealm; use oauth_authorization_server::config::ServerConfig; use oauth_authorization_server::state::ServerState; use oauth_authorization_server::AuthorizationServerManager; -use axum::routing::{get, head}; -use axum::{Json, Router}; use photos_network_plugin::{PluginFactoryRef, PluginId}; use serde::{Deserialize, Serialize}; -use tokio::task; use std::path::Path; use tower_http::services::ServeDir; use tower_http::trace::TraceLayer; @@ -111,6 +110,7 @@ pub async fn start_server() -> Result<()> { // authorization server .nest("/", AuthorizationServerManager::routes(server)) + .nest("/api", MediaApi::routes()) // oauth 2 // .nest("/oauth", api::authentication::AutenticationManager::routes()) .layer(TraceLayer::new_for_http()) @@ -173,9 +173,9 @@ pub async fn start_server() -> Result<()> { let addr: SocketAddr = SocketAddr::from(([0, 0, 0, 0], 7777)); tracing::debug!("listening on {}", addr); axum::Server::bind(&addr) - .serve(router.into_make_service()) - .await - .unwrap(); + .serve(router.into_make_service()) + .await + .unwrap(); Ok(()) }