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(())
}