Skip to content

Commit

Permalink
Implement POST /videos endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksbgbg committed Feb 21, 2024
1 parent e3af34e commit ad64560
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 8 deletions.
1 change: 1 addition & 0 deletions backend-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend-rs/streamfox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ fs-file = { version = "0.0.0", path = "../fs-file", default-features = false }
jsonwebtoken = { version = "9.2.0", default-features = false }
lazy_static = "1.4.0"
migration = { version = "0.0.0", path = "../migration", default-features = false }
mime = { version = "0.3.17", default-features = false }
ring = "0.17.7"
sea-orm = { version = "0.12.14", features = ["runtime-tokio-rustls", "sqlx-postgres", "debug-print"] }
sea-orm-migration = { version = "0.12.14", default-features = false }
Expand Down
27 changes: 27 additions & 0 deletions backend-rs/streamfox/src/controllers/video.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::controllers::errors::HandlerError;
use crate::controllers::user::UserResponse;
use crate::models::user::User;
use crate::models::video;
use crate::AppState;
use axum::extract::State;
use axum::http::StatusCode;
use axum::Json;
use chrono::{DateTime, Utc};
use entity::id::Id;
Expand Down Expand Up @@ -46,3 +48,28 @@ pub async fn get_videos(
.collect(),
))
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct VideoCreatedResponse {
id: Id,
name: String,
description: String,
visibility: Visibility,
}

pub async fn create_video(
State(state): State<AppState>,
user: User,
) -> Result<(StatusCode, Json<VideoCreatedResponse>), HandlerError> {
let video = video::create(&state.connection, &state.snowflakes, user).await?;
Ok((
StatusCode::CREATED,
Json(VideoCreatedResponse {
id: video.id,
name: video.name,
description: video.description,
visibility: video.visibility,
}),
))
}
3 changes: 3 additions & 0 deletions backend-rs/streamfox/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ struct AppState {

struct Snowflakes {
user_snowflake: SnowflakeGenerator,
video_snowflake: SnowflakeGenerator,
}

#[tokio::main]
Expand Down Expand Up @@ -94,6 +95,7 @@ async fn main() -> Result<(), AppError> {
.route("/auth/login", routing::post(user::login))
.route("/user", routing::get(user::get_user))
.route("/videos", routing::get(video::get_videos))
.route("/videos", routing::post(video::create_video))
.layer(
TraceLayer::new_for_http()
.make_span_with(DefaultMakeSpan::new().level(Level::INFO))
Expand All @@ -104,6 +106,7 @@ async fn main() -> Result<(), AppError> {
connection,
snowflakes: Arc::new(Snowflakes {
user_snowflake: SnowflakeGenerator::new(0),
video_snowflake: SnowflakeGenerator::new(1),
}),
});
let api = Router::new().nest("/api", app);
Expand Down
6 changes: 6 additions & 0 deletions backend-rs/streamfox/src/models/base.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use crate::snowflake::SnowflakeGenerator;
use entity::id::Id;
use sea_orm::{ColumnTrait, DatabaseConnection, DbErr, EntityTrait, QueryFilter, Value};

pub async fn new_id(snowflake: &SnowflakeGenerator) -> Id {
Id::from(snowflake.generate_id().await)
}

pub async fn exists<E: EntityTrait>(
connection: &DatabaseConnection,
column: impl ColumnTrait,
Expand Down
10 changes: 5 additions & 5 deletions backend-rs/streamfox/src/models/user.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::models::base::exists;
use crate::models::base;
use crate::secure::{random_bytes, Bytes};
use crate::{MainFs, Snowflakes};
use base64::engine::general_purpose;
Expand Down Expand Up @@ -84,11 +84,11 @@ pub async fn create_default_users(
}

async fn id_exists(connection: &DatabaseConnection, id: Id) -> Result<bool, DbErr> {
exists::<user::Entity>(connection, user::Column::Id, id).await
base::exists::<user::Entity>(connection, user::Column::Id, id).await
}

pub async fn name_exists(connection: &DatabaseConnection, name: &str) -> Result<bool, DbErr> {
exists::<user::Entity>(
base::exists::<user::Entity>(
connection,
user::Column::CanonicalUsername,
name.to_lowercase(),
Expand All @@ -97,7 +97,7 @@ pub async fn name_exists(connection: &DatabaseConnection, name: &str) -> Result<
}

pub async fn email_exists(connection: &DatabaseConnection, email: &str) -> Result<bool, DbErr> {
exists::<user::Entity>(
base::exists::<user::Entity>(
connection,
user::Column::CanonicalEmailAddress,
email.to_lowercase(),
Expand Down Expand Up @@ -127,7 +127,7 @@ pub async fn create(
Ok(
create_base(
connection,
Id::from(snowflakes.user_snowflake.generate_id().await),
base::new_id(&snowflakes.user_snowflake).await,
Some(user.username),
Some(user.email_address),
Some(user.password),
Expand Down
54 changes: 51 additions & 3 deletions backend-rs/streamfox/src/models/video.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use crate::models::base;
use crate::models::user::User;
use chrono::{DateTime, Utc};
use crate::Snowflakes;
use chrono::{DateTime, Local, Utc};
use entity::id::Id;
use entity::video::Visibility;
use entity::video::{Status, Visibility};
use entity::{user, video, view};
use sea_orm::{
ColumnTrait, DatabaseConnection, DbErr, EntityTrait, FromQueryResult, JoinType, QuerySelect,
ActiveModelTrait, ActiveValue, ColumnTrait, DatabaseConnection, DbErr, EntityTrait,
FromQueryResult, JoinType, QuerySelect,
};

#[derive(FromQueryResult)]
Expand Down Expand Up @@ -47,3 +50,48 @@ pub async fn find_all(connection: &DatabaseConnection) -> Result<Vec<(VideoResul
})
.collect()
}

pub struct Video {
pub id: Id,
pub name: String,
pub description: String,
pub visibility: Visibility,
}

impl From<video::Model> for Video {
fn from(value: video::Model) -> Self {
Video {
id: value.id,
name: value.name,
description: value.description,
visibility: value.visibility,
}
}
}

pub async fn create(
connection: &DatabaseConnection,
snowflakes: &Snowflakes,
creator: User,
) -> Result<Video, DbErr> {
let time = Local::now().fixed_offset();
Ok(
video::ActiveModel {
id: ActiveValue::set(base::new_id(&snowflakes.video_snowflake).await),
created_at: ActiveValue::set(time),
updated_at: ActiveValue::set(time),
status: ActiveValue::set(Status::Created),
mime_type: ActiveValue::set(mime::APPLICATION_OCTET_STREAM.to_string()),
duration_secs: ActiveValue::set(0),
size_bytes: ActiveValue::set(0),
subtitles_extracted: ActiveValue::set(false),
creator_id: ActiveValue::set(creator.id),
name: ActiveValue::set("Untitled Video".into()),
description: ActiveValue::set(String::new()),
visibility: ActiveValue::set(Visibility::Public),
}
.insert(connection)
.await?
.into(),
)
}

0 comments on commit ad64560

Please sign in to comment.