Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add seasons, and the ability to filter on them #80

Merged
merged 17 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ done
# Build the docker containers if clean flag is set

if [ "$clean" = true ]; then
# rm vingo/.env || true
rm vingo/.env || true
rm vinvoor/.env || true
docker compose -f docker-compose.yml build
fi


# Check for the required files

#if [ ! -f vingo/.env ]; then
# cp vingo/dev.env vingo/.env
#fi
if [ ! -f vingo/.env ]; then
cp vingo/dev.env vingo/.env
fi
if [ ! -f vinvoor/.env ]; then
cp vinvoor/dev.env vinvoor/.env
fi
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ services:
- "host.docker.internal:host-gateway"

zess-backend:
env_file: "vingo/.env"
build:
context: vingo
dockerfile: Dockerfile.dev
Expand All @@ -22,6 +23,7 @@ services:
- ./vingo:/backend
extra_hosts:
- "host.docker.internal:host-gateway"
stop_grace_period: 1s
depends_on:
- zess-db

Expand Down
1 change: 1 addition & 0 deletions vingo/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 vingo/dev.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DEBUG_LOGIN="TRUE"
2 changes: 2 additions & 0 deletions vingo/migration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ path = "src/lib.rs"

[dependencies]
async-std = { version = "1", features = ["attributes", "tokio1"] }
chrono = { version = "0.4.38", default-features = false, features = ["serde"] }

[dependencies.sea-orm-migration]
version = "1.0.0"
Expand All @@ -18,3 +19,4 @@ features = [
"runtime-tokio-rustls",
"with-chrono",
]

20 changes: 18 additions & 2 deletions vingo/migration/src/m20240909_214352_create_seasons.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use chrono::NaiveDate;
use sea_orm_migration::{prelude::*, schema::*};

#[derive(DeriveMigrationName)]
Expand Down Expand Up @@ -25,12 +26,27 @@ impl MigrationTrait for Migration {
.col(date(Season::End))
.to_owned(),
)
.await
.await?;

// insert the first season (which is all data)
let insert = Query::insert()
.into_table(Season::Table)
.columns([Season::Name, Season::Start, Season::End])
.values_panic([
"All".into(),
NaiveDate::from_ymd_opt(2000, 1, 1).unwrap().into(),
NaiveDate::from_ymd_opt(3000, 1, 1).unwrap().into(),
])
.to_owned();

manager.exec_stmt(insert).await?;

Ok(())
}

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Season::Table).to_owned())
.await
}
}
}
10 changes: 4 additions & 6 deletions vingo/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,16 @@ fn authenticated_routes() -> Router<AppState> {
)
.route("/scans", get(scans::get_for_current_user))
.route("/leaderboard", get(leaderboard::get))
.route("/settings/seasons/:season_id", post(settings::set_season))
.route("/seasons", get(seasons::get_until_now))
.route("/settings", get(settings::get).patch(settings::update))
.route_layer(from_fn(middleware::is_logged_in))
}

fn admin_routes() -> Router<AppState> {
Router::new()
.route(
"/days",
get(days::get).post(days::add_multiple),
)
.route("/days", get(days::get).post(days::add_multiple))
.route("/days/:day_id", delete(days::delete))
.route("/seasons", get(seasons::get).post(seasons::add))
.route("/seasons", get(seasons::get_all).post(seasons::add))
.route("/seasons/:season_id", delete(seasons::delete))
.route_layer(from_fn(middleware::is_admin))
}
6 changes: 1 addition & 5 deletions vingo/src/middleware.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use axum::{
extract::Request,
middleware::Next,
response::{IntoResponse, Response},
};
use axum::{extract::Request, middleware::Next, response::IntoResponse};
use reqwest::StatusCode;
use tower_sessions::Session;

Expand Down
13 changes: 8 additions & 5 deletions vingo/src/routes/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use chrono::Local;
use rand::distributions::{Alphanumeric, DistString};
use reqwest::StatusCode;
use sea_orm::sea_query::OnConflict;
use sea_orm::{EntityTrait, Set, TryIntoModel};
use sea_orm::{EntityTrait, Set};
use serde::{Deserialize, Serialize};
use tower_sessions::Session;
use user::Model;
Expand Down Expand Up @@ -133,10 +133,13 @@ pub async fn callback(
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "user insert error"))?;

session.clear().await;
session.insert(SessionKeys::User.as_str(), db_user).await.or_log((
StatusCode::INTERNAL_SERVER_ERROR,
"failed to insert user in session",
))?;
session
.insert(SessionKeys::User.as_str(), db_user)
.await
.or_log((
StatusCode::INTERNAL_SERVER_ERROR,
"failed to insert user in session",
))?;

Ok(Redirect::to(FRONTEND_URL))
}
3 changes: 1 addition & 2 deletions vingo/src/routes/days.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use axum::{
extract::{Path, State},
Json,
};
use chrono::{DateTime, Datelike, FixedOffset, NaiveDate, TimeDelta, Weekday};
use chrono::{Datelike, NaiveDate, TimeDelta, Weekday};
use reqwest::StatusCode;
use sea_orm::{ActiveModelTrait, EntityTrait, Set, TransactionTrait};
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -38,7 +38,6 @@ pub async fn add_multiple(

let mut current_date = day_range.start_date;
while current_date <= day_range.end_date {

if current_date.weekday() == Weekday::Sat || current_date.weekday() == Weekday::Sun {
current_date += TimeDelta::days(1);
continue;
Expand Down
6 changes: 5 additions & 1 deletion vingo/src/routes/scans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use tower_sessions::Session;

use super::util::{
errors::{ResponseResult, ResultAndLogError},
session::get_user,
session::{get_season, get_user},
};

const SCAN_KEY: &str = "bad_key";
Expand All @@ -24,10 +24,14 @@ pub async fn get_for_current_user(
state: State<AppState>,
) -> ResponseResult<Json<Vec<scan::Model>>> {
let user = get_user(&session).await?;
let season = get_season(&session, &state).await?;
let scans = Scan::find()
.join(InnerJoin, scan::Relation::Card.def())
.join(InnerJoin, card::Relation::User.def())
.filter(user::Column::Id.eq(user.id))
// scan time > start && scan_time < end
.filter(scan::Column::ScanTime.gte(season.start))
.filter(scan::Column::ScanTime.lte(season.end))
.all(&state.db)
.await
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to get scans"))?;
Expand Down
56 changes: 47 additions & 9 deletions vingo/src/routes/seasons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ use axum::{
extract::{Path, State},
Json,
};
use chrono::{DateTime, Datelike, FixedOffset, NaiveDate, TimeDelta, Weekday};
use chrono::NaiveDate;

use reqwest::StatusCode;
use sea_orm::{ActiveModelTrait, EntityTrait, Set, TransactionTrait};
use sea_orm::{sea_query::Expr, DatabaseConnection};
use sea_orm::{
ActiveModelTrait, EntityTrait, FromQueryResult, QueryFilter, QuerySelect, QueryTrait, Set,
};
use serde::{Deserialize, Serialize};

use crate::{
Expand All @@ -14,11 +18,39 @@ use crate::{

use super::util::errors::{ResponseResult, ResultAndLogError};

pub async fn get(state: State<AppState>) -> ResponseResult<Json<Vec<season::Model>>> {
Ok(Json(Season::find().all(&state.db).await.or_log((
StatusCode::INTERNAL_SERVER_ERROR,
"failed to get seasons",
))?))
#[derive(Debug, FromQueryResult, Serialize, Deserialize)]
pub struct SeasonGet {
id: i32,
name: String,
start: NaiveDate,
end: NaiveDate,
is_current: bool,
}

pub async fn get_until_now(state: State<AppState>) -> ResponseResult<Json<Vec<SeasonGet>>> {
Ok(Json(db_seasons(&state.db, false).await?))
}

pub async fn get_all(state: State<AppState>) -> ResponseResult<Json<Vec<SeasonGet>>> {
Ok(Json(db_seasons(&state.db, true).await?))
}

pub async fn db_seasons(db: &DatabaseConnection, future: bool) -> ResponseResult<Vec<SeasonGet>> {
Ok(Season::find()
.column_as(
Expr::col(season::Column::Start)
.lte(Expr::current_date())
.and(Expr::col(season::Column::End).gte(Expr::current_date()))
.and(Expr::col(season::Column::Id).ne(1)),
"is_current",
)
.apply_if((!future).then_some(()), |query, _| {
query.filter(Expr::col(season::Column::Start).lt(Expr::current_date()))
})
.into_model::<SeasonGet>()
.all(db)
.await
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to get seasons"))?)
}

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -27,13 +59,19 @@ pub struct SeasonAddBody {
start: NaiveDate,
end: NaiveDate,
}
pub async fn add(state: State<AppState>, Json(new_season): Json<SeasonAddBody>) -> ResponseResult<()> {
pub async fn add(
state: State<AppState>,
Json(new_season): Json<SeasonAddBody>,
) -> ResponseResult<()> {
season::ActiveModel {
name: Set(new_season.name),
start: Set(new_season.start),
end: Set(new_season.end),
..Default::default()
}.insert(&state.db).await.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to insert season"))?;
}
.insert(&state.db)
.await
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to insert season"))?;

Ok(())
}
Expand Down
52 changes: 43 additions & 9 deletions vingo/src/routes/settings.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
use axum::extract::{Path, State};
use axum::{extract::State, Json};
use reqwest::StatusCode;
use sea_orm::EntityTrait;
use serde::{Deserialize, Serialize};
use tower_sessions::Session;

use crate::{
entities::{prelude::*, *},
AppState,
};
use crate::{entities::prelude::*, AppState};

use super::util::{errors::{ResponseResult, ResultAndLogError}, session::{self, SessionKeys}};
use super::util::{
errors::{ResponseResult, ResultAndLogError},
session::{get_season, SessionKeys},
};

#[derive(Debug, Serialize, Deserialize)]
pub struct SettingsGetBody {
season: i32,
}
pub async fn get(
session: Session,
state: State<AppState>,
) -> ResponseResult<Json<SettingsGetBody>> {
let season = get_season(&session, &state).await?;
Ok(Json(SettingsGetBody { season: season.id }))
}

pub async fn set_season(state: State<AppState>, session: Session, Path(season_id): Path<i32>) -> ResponseResult<()> {
session.insert(SessionKeys::Season.as_str(), season_id).await.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to insert season into session"))?;
#[derive(Debug, Serialize, Deserialize)]
pub struct SettingsUpdateBody {
season: Option<i32>,
}
pub async fn update(
session: Session,
state: State<AppState>,
Json(settings): Json<SettingsUpdateBody>,
) -> ResponseResult<()> {
if let Some(season_id) = settings.season {
let season = Season::find_by_id(season_id)
.one(&state.db)
.await
.or_log((StatusCode::INTERNAL_SERVER_ERROR, "failed to get season"))?
.ok_or((StatusCode::INTERNAL_SERVER_ERROR, "no season 0"))?;
session
.insert(SessionKeys::Season.as_str(), season)
.await
.or_log((
StatusCode::INTERNAL_SERVER_ERROR,
"failed to insert season into session",
))?;
}

Ok(())
}
}
Loading
Loading