Skip to content

Feature/streaks #23

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

Merged
merged 4 commits into from
Dec 6, 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
2 changes: 2 additions & 0 deletions migrations/20241126123155_adding_streaks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE Member ADD COLUMN streak INT;
ALTER TABLE Member ADD COLUMN max_streak INT;
1 change: 1 addition & 0 deletions migrations/20241126162522_add_member_group.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE Member ADD COLUMN group_id INT;
6 changes: 6 additions & 0 deletions migrations/20241128224140_add_streak_relation.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE Streaks (
id SERIAL PRIMARY KEY,
streak INT NOT NULL DEFAULT 0,
max_streak INT NOT NULL DEFAULT 0,
FOREIGN KEY (id) REFERENCES Member(id) ON DELETE CASCADE
);
3 changes: 3 additions & 0 deletions migrations/20241129193435_remove_streks_from_membertable.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ALTER TABLE Member
DROP COLUMN streak,
DROP COLUMN max_streak;
6 changes: 6 additions & 0 deletions migrations/20241129195135_add_streaks_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE StreakUpdate (
id SERIAL PRIMARY KEY,
streak INT NOT NULL DEFAULT 0,
max_streak INT NOT NULL DEFAULT 0,
FOREIGN KEY (id) REFERENCES Member(id) ON DELETE CASCADE
);
1 change: 1 addition & 0 deletions migrations/20241129195234_drop_old_streak_table.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE Streaks;
1 change: 1 addition & 0 deletions migrations/20241129200327_drop_strek_update.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS StreakUpdate;
6 changes: 6 additions & 0 deletions migrations/20241129200519_recreate_streaks.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE StreakUpdate (
id SERIAL PRIMARY KEY,
streak INT NOT NULL DEFAULT 0,
max_streak INT NOT NULL DEFAULT 0,
FOREIGN KEY (id) REFERENCES Member(id) ON DELETE CASCADE
);
8 changes: 8 additions & 0 deletions src/db/member.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,12 @@ pub struct Member {
pub year: i32,
pub macaddress: String,
pub discord_id: Option<String>,
pub group_id: Option<i32>,
}

#[derive(FromRow, SimpleObject)]
pub struct StreakUpdate {
pub id: i32,
pub streak: Option<i32>,
pub max_streak: Option<i32>,
}
82 changes: 75 additions & 7 deletions src/graphql/mutations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use sha2::Sha256;

type HmacSha256 = Hmac<Sha256>;

use crate::db::{member::Member, attendance::Attendance};
use crate::db::{member::Member, attendance::Attendance, member::StreakUpdate};

pub struct MutationRoot;

Expand All @@ -30,14 +30,15 @@ impl MutationRoot {
year: i32,
macaddress: String,
discord_id: String,
group_id: i32,

) -> Result<Member, sqlx::Error> {
let pool = ctx.data::<Arc<PgPool>>().expect("Pool not found in context");



let member = sqlx::query_as::<_, Member>(
"INSERT INTO Member (rollno, name, hostel, email, sex, year, macaddress, discord_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *"
"INSERT INTO Member (rollno, name, hostel, email, sex, year, macaddress, discord_id, group_id) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING *"
)
.bind(rollno)
.bind(name)
Expand All @@ -47,6 +48,7 @@ impl MutationRoot {
.bind(year)
.bind(macaddress)
.bind(discord_id)
.bind(group_id)
.fetch_one(pool.as_ref())
.await?;

Expand All @@ -61,6 +63,7 @@ impl MutationRoot {
year: i32,
macaddress: String,
discord_id: String,
group_id: i32,
hmac_signature: String,
) -> Result<Member,sqlx::Error> {
let pool = ctx.data::<Arc<PgPool>>().expect("Pool not found in context");
Expand All @@ -69,7 +72,7 @@ impl MutationRoot {

let mut mac = HmacSha256::new_from_slice(secret_key.as_bytes()).expect("HMAC can take key of any size");

let message = format!("{}{}{}{}{}", id, hostel, year, macaddress, discord_id);
let message = format!("{}{}{}{}{}{}", id, hostel, year, macaddress, discord_id, group_id);
mac.update(message.as_bytes());

let expected_signature = mac.finalize().into_bytes();
Expand All @@ -91,8 +94,9 @@ impl MutationRoot {
hostel = CASE WHEN $1 = '' THEN hostel ELSE $1 END,
year = CASE WHEN $2 = 0 THEN year ELSE $2 END,
macaddress = CASE WHEN $3 = '' THEN macaddress ELSE $3 END,
discord_id = CASE WHEN $4 = '' THEN discord_id ELSE $4 END
WHERE id = $5
discord_id = CASE WHEN $4 = '' THEN discord_id ELSE $4 END,
group_id = CASE WHEN $5 = 0 THEN group_id ELSE $5 END
WHERE id = $6
RETURNING *
"
)
Expand All @@ -101,6 +105,7 @@ impl MutationRoot {
.bind(year)
.bind(macaddress)
.bind(discord_id)
.bind(group_id)
.bind(id)
.fetch_one(pool.as_ref())
.await?;
Expand Down Expand Up @@ -158,7 +163,6 @@ impl MutationRoot {
mac.update(message.as_bytes());

let expected_signature = mac.finalize().into_bytes();


// Convert the received HMAC signature from the client to bytes for comparison
let received_signature = hex::decode(hmac_signature)
Expand Down Expand Up @@ -192,4 +196,68 @@ impl MutationRoot {

Ok(attendance)
}
}
async fn update_streak(
&self,
ctx: &Context<'_>,
id: i32,
has_sent_update: bool,
) -> Result<StreakUpdate, sqlx::Error> {
let pool = ctx.data::<Arc<PgPool>>().expect("Pool not found in context");

let streak_info = sqlx::query_as::<_, StreakUpdate>(
"
SELECT id, streak, max_streak
FROM StreakUpdate
WHERE id = $1
"
)
.bind(id)
.fetch_optional(pool.as_ref())
.await?;

match streak_info{
Some(mut member) => {
let current_streak = member.streak.unwrap_or(0);
let max_streak = member.max_streak.unwrap_or(0);
let (new_streak, new_max_streak) = if has_sent_update {
let updated_streak = current_streak + 1;
let updated_max_streak = updated_streak.max(max_streak);
(updated_streak, updated_max_streak)
} else {
(0, max_streak)
};
let updated_member = sqlx::query_as::<_, StreakUpdate>(
"
UPDATE StreakUpdate
SET streak = $1, max_streak = $2
WHERE id = $3
RETURNING *
"
)
.bind(new_streak)
.bind(new_max_streak)
.bind(id)
.fetch_one(pool.as_ref())
.await?;

Ok(updated_member)
},
None => {
let new_member = sqlx::query_as::<_, StreakUpdate>(
"
INSERT INTO StreakUpdate (id, streak, max_streak)
VALUES ($1, $2, $3)
RETURNING *
"
)
.bind(id)
.bind(0)
.bind(0)
.fetch_one(pool.as_ref())
.await?;

Ok(new_member)
}
}
}
}
15 changes: 14 additions & 1 deletion src/graphql/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::sync::Arc;
use chrono::NaiveDate;


use crate::db::{member::Member, attendance::Attendance};
use crate::db::{member::Member, attendance::Attendance, member::StreakUpdate};

pub struct QueryRoot;

Expand Down Expand Up @@ -36,4 +36,17 @@ impl QueryRoot {
.await?;
Ok(attendance_list)
}
async fn get_streak(
&self,
ctx: &Context<'_>,
id: i32,
) -> Result<StreakUpdate, sqlx::Error> {
let pool = ctx.data::<Arc<PgPool>>().expect("Pool not found in context");
let streak = sqlx::query_as::<_, StreakUpdate>("SELECT * FROM StreakUpdate WHERE id = $1")
.bind(id)
.fetch_one(pool.as_ref())
.await?;

Ok(streak)
}
}