Skip to content

Commit

Permalink
add media repository
Browse files Browse the repository at this point in the history
  • Loading branch information
thebino committed Aug 27, 2023
1 parent a154ea8 commit 33b2f41
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 75 deletions.
1 change: 1 addition & 0 deletions crates/common/src/http/extractors/optuser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ where
{
type Rejection = String;

#[allow(clippy::bind_instead_of_map)]
async fn from_request_parts(parts: &mut Parts, _: &S) -> Result<Self, Self::Rejection> {
parts
.headers
Expand Down
2 changes: 1 addition & 1 deletion crates/common/src/model/auth/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use uuid::Uuid;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct User {
uuid: Uuid,
pub uuid: Uuid,
email: String,
password: Option<String>,
lastname: Option<String>,
Expand Down
13 changes: 11 additions & 2 deletions crates/media/src/api/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::sync::Arc;

use axum::routing::{delete, get, patch, post};
use axum::Router;

use crate::repository::repository::{MediaRepository, MediaRepositoryState};

use super::routes::delete_media_id::delete_media_id;
use super::routes::get_albums::get_albums;
use super::routes::get_albums_id::get_albums_id;
Expand All @@ -38,6 +42,11 @@ impl MediaApi {
where
S: Send + Sync + 'static + Clone,
{
let media_repository: MediaRepositoryState = Arc::new(MediaRepository {
db_url: "",
db: sea_orm::DatabaseConnection::Disconnected,
});

Router::new()
// Returns a list of owned media items for current user
// 200 Ok
Expand All @@ -56,8 +65,7 @@ impl MediaApi {
// 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.
// 500 Internal Server Error
// 403 Forbidden - You are authenticated but have no permission to manage the target user. // 500 Internal Server Error
.route("/media/:media_id", get(get_media_id))
// Add files for a specific media item
.route("/media/:media_id", post(post_media_id))
Expand All @@ -78,6 +86,7 @@ impl MediaApi {
// unshares the given album
.route("/albums/:entity_id/unshare", patch(patch_albums_id_unshare))
.layer(tower_http::trace::TraceLayer::new_for_http())
.with_state(media_repository)
}
}

Expand Down
23 changes: 18 additions & 5 deletions crates/media/src/api/routes/get_media.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//! Returns a list of owned media items for current user
//!
use axum::extract::State;
use axum::{extract::Query, http::StatusCode, Json};
use common::http::extractors::{self, optuser::OptionalUser};
use common::model::auth::user::User;
use serde::{Deserialize, Serialize};
use std::result::Result;
use tracing::error;

use crate::repository::repository::MediaRepositoryState;

#[derive(Serialize, Deserialize)]
pub(crate) struct MediaListQuery {
Expand All @@ -13,18 +16,28 @@ pub(crate) struct MediaListQuery {
}

pub(crate) async fn get_media(
user: OptionalUser,
State(repo): State<MediaRepositoryState>,
user: User,
Query(query): Query<MediaListQuery>,
) -> Result<Json<String>, StatusCode> {
let items = repo.get_media_items_for_user(user.uuid).await;
match items {
Ok(i) => {
error!("Found {} items for user.", i.len());
}
Err(_) => {
error!("Failed to get media items!");
}
}
//tracing::error!("GET /media user={}", user);
// TODO: check auth header
// TODO: read list from persistency
// TODO: return list
Ok(Json(
format!(
"list media items. limit={}, offset={}",
query.limit.unwrap_or_else(|| 1000),
query.offset.unwrap_or_else(|| 0)
query.limit.unwrap_or(1000),
query.offset.unwrap_or(0)
)
.to_owned(),
))
Expand Down Expand Up @@ -58,6 +71,6 @@ mod tests {
.unwrap();

// then
assert_eq!(response.status(), StatusCode::OK);
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
}
}
2 changes: 1 addition & 1 deletion crates/media/src/data/media_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl MediaItem {
fn new(name: &'static str) -> Self {
MediaItem {
uuid: "",
name: name,
name,
date_added: Instant::now(),
date_taken: None,
location: None,
Expand Down
64 changes: 1 addition & 63 deletions crates/media/src/repository/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,66 +15,4 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

use std::sync::Arc;

use axum::async_trait;
use mockall::predicate::*;
use sea_orm::DatabaseConnection;

use crate::data::error::DataAccessError;
use crate::data::media_item::MediaItem;
use crate::data::open_db_conn;

pub struct MediaRepository {
#[allow(dead_code)]
db_url: &'static str,
#[allow(dead_code)]
db: DatabaseConnection,
}

#[allow(dead_code)]
pub(crate) type MediaRepositoryState = Arc<MediaRepository>;

/// MockPhotosRepositoryTrait is created by automock macro
#[cfg_attr(test, mockall::automock)]
#[async_trait]
trait MediaRepositoryTrait {
#[allow(dead_code)]
async fn new(db_url: &'static str) -> Self;

// Gets a list of media items from the DB filted by user_id
async fn get_media_items_for_user(
&self,
user_id: &str,
) -> Result<Vec<MediaItem>, DataAccessError>;
}

impl MediaRepository {
#[allow(dead_code)]
pub(crate) async fn new() -> Self {
Self {
db_url: "",
db: DatabaseConnection::Disconnected,
}
}
}

#[async_trait]
impl MediaRepositoryTrait for MediaRepository {
async fn new(db_url: &'static str) -> MediaRepository {
let db = open_db_conn("sqlite://data/media.sqlita".to_string())
.await
.expect("Could not connect do database 'media'!");

MediaRepository { db, db_url }
}

async fn get_media_items_for_user(
&self,
_user_id: &str,
) -> Result<Vec<MediaItem>, DataAccessError> {
// TODO: read from database

Err(DataAccessError::OtherError)
}
}
pub mod repository;

Check failure on line 18 in crates/media/src/repository/mod.rs

View workflow job for this annotation

GitHub Actions / Lints

module has the same name as its containing module
90 changes: 90 additions & 0 deletions crates/media/src/repository/repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* 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 <https://www.gnu.org/licenses/>.
*/

use std::sync::Arc;

use axum::async_trait;
use mockall::predicate::*;
use sea_orm::DatabaseConnection;
use tracing::info;
use uuid::Uuid;

use crate::data::error::DataAccessError;
use crate::data::media_item::MediaItem;
use crate::data::open_db_conn;

pub struct MediaRepository {
#[allow(dead_code)]
pub(crate) db_url: &'static str,
#[allow(dead_code)]
pub(crate) db: DatabaseConnection,
}

#[allow(dead_code)]
pub(crate) type MediaRepositoryState = Arc<MediaRepository>;

/// MockPhotosRepositoryTrait is created by automock macro
#[cfg_attr(test, mockall::automock)]
#[async_trait]
trait MediaRepositoryTrait {
#[allow(dead_code)]
async fn new(db_url: &'static str) -> Self;

// Gets a list of media items from the DB filted by user_id
async fn get_media_items_for_user(
&self,
user_id: Uuid,
) -> Result<Vec<MediaItem>, DataAccessError>;
}

impl MediaRepository {
#[allow(dead_code)]
pub(crate) async fn new() -> Self {
Self {
db_url: "sqlite://data/media.sqlite",
db: DatabaseConnection::Disconnected,
}
}
pub(crate) async fn get_media_items_for_user(
&self,
user_id: Uuid,
) -> Result<Vec<MediaItem>, DataAccessError> {
info!("get items for user {}", user_id);

Ok(vec![])
}
}

#[async_trait]
impl MediaRepositoryTrait for MediaRepository {
async fn new(db_url: &'static str) -> MediaRepository {
let db = open_db_conn(db_url.to_string())
.await
.expect("Could not connect do database 'media'!");

MediaRepository { db, db_url }
}

async fn get_media_items_for_user(
&self,
_user_id: Uuid,
) -> Result<Vec<MediaItem>, DataAccessError> {
// TODO: read from database

Err(DataAccessError::OtherError)
}
}
10 changes: 7 additions & 3 deletions crates/oauth_authentication/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ use thiserror::Error;
use openidconnect::{OAuth2TokenResponse, TokenResponse};

pub struct AuthenticationManager {
#[allow(clippy::type_complexity)]
pub client: openidconnect::Client<
openidconnect::EmptyAdditionalClaims,
openidconnect::core::CoreAuthDisplay,
Expand Down Expand Up @@ -68,6 +69,7 @@ pub struct AuthenticationManager {
openidconnect::core::CoreRevocableToken,
openidconnect::StandardErrorResponse<openidconnect::RevocationErrorResponseType>,
>,
#[allow(clippy::type_complexity)]
pub provider_metadata: ProviderMetadata<
EmptyAdditionalProviderMetadata,
openidconnect::core::CoreAuthDisplay,
Expand Down Expand Up @@ -105,7 +107,7 @@ impl AuthenticationManager {
pub fn new() -> Result<Self, anyhow::Error> {
tracing::error!("run setup");

let foo = CoreProviderMetadata::discover(
let provider_metadata = CoreProviderMetadata::discover(
&IssuerUrl::new("https://accounts.google.com".to_string())?,
http_client,
)?;
Expand All @@ -115,9 +117,9 @@ impl AuthenticationManager {
PkceCodeChallenge::new_random_sha256();

Ok(Self {
provider_metadata: foo.clone(),
provider_metadata: provider_metadata.clone(),
client: CoreClient::from_provider_metadata(
foo,
provider_metadata,
ClientId::new(
"953760225864-77il4losuech1dtsea36tmma2e8bko3h.apps.googleusercontent.com"
.to_string(),
Expand All @@ -133,6 +135,7 @@ impl AuthenticationManager {
})
}

#[allow(clippy::type_complexity)]
pub fn create_authorization_url(
client: openidconnect::Client<
openidconnect::EmptyAdditionalClaims,
Expand Down Expand Up @@ -188,6 +191,7 @@ impl AuthenticationManager {
Ok(nonce)
}

#[allow(clippy::type_complexity)]
pub fn exchange_code(
client: openidconnect::Client<
openidconnect::EmptyAdditionalClaims,
Expand Down
5 changes: 5 additions & 0 deletions documentation/http/get_media.hurl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GET http://127.0.0.1:7777/media
Authorization: FakeToken

HTTP 200

0 comments on commit 33b2f41

Please sign in to comment.