Compare commits
No commits in common. "07493b83a5aa883b28463016688d3c3391f8e800" and "f7b7ebbb1c5cca8168e3f4953d31c6f92beedcf2" have entirely different histories.
07493b83a5
...
f7b7ebbb1c
65
server/Cargo.lock
generated
65
server/Cargo.lock
generated
@ -138,7 +138,6 @@ dependencies = [
|
|||||||
"axum",
|
"axum",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cookie",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"headers",
|
"headers",
|
||||||
"http",
|
"http",
|
||||||
@ -285,17 +284,6 @@ version = "0.9.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cookie"
|
|
||||||
version = "0.18.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
|
||||||
dependencies = [
|
|
||||||
"percent-encoding",
|
|
||||||
"time",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation-sys"
|
name = "core-foundation-sys"
|
||||||
version = "0.8.7"
|
version = "0.8.7"
|
||||||
@ -418,15 +406,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "deranged"
|
|
||||||
version = "0.3.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
|
||||||
dependencies = [
|
|
||||||
"powerfmt",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
@ -1153,12 +1132,6 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-conv"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num-integer"
|
||||||
version = "0.1.46"
|
version = "0.1.46"
|
||||||
@ -1304,12 +1277,6 @@ version = "0.3.31"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "powerfmt"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
@ -1959,37 +1926,6 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time"
|
|
||||||
version = "0.3.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21"
|
|
||||||
dependencies = [
|
|
||||||
"deranged",
|
|
||||||
"itoa",
|
|
||||||
"num-conv",
|
|
||||||
"powerfmt",
|
|
||||||
"serde",
|
|
||||||
"time-core",
|
|
||||||
"time-macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-core"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "time-macros"
|
|
||||||
version = "0.2.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de"
|
|
||||||
dependencies = [
|
|
||||||
"num-conv",
|
|
||||||
"time-core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tinystr"
|
name = "tinystr"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@ -2537,7 +2473,6 @@ dependencies = [
|
|||||||
"argon2",
|
"argon2",
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
"bitflags",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"csv",
|
"csv",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
@ -6,7 +6,7 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
# Primary crates
|
# Primary crates
|
||||||
axum = { version = "0.8", features = [ "macros", "json" ] }
|
axum = { version = "0.8", features = [ "macros", "json" ] }
|
||||||
axum-extra = { version = "0.10.0", features = [ "typed-header", "cookie" ] }
|
axum-extra = { version = "0.10.0", features = [ "typed-header" ] }
|
||||||
tokio = { version = "1.43", features = [ "rt-multi-thread", "macros" ] }
|
tokio = { version = "1.43", features = [ "rt-multi-thread", "macros" ] }
|
||||||
sqlx = { version = "0.8", features = [ "runtime-tokio", "postgres", "uuid", "chrono" ] }
|
sqlx = { version = "0.8", features = [ "runtime-tokio", "postgres", "uuid", "chrono" ] }
|
||||||
|
|
||||||
@ -16,7 +16,6 @@ serde = "1.0"
|
|||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
validator = { version = "0.19.0", features = [ "derive" ] }
|
validator = { version = "0.19.0", features = [ "derive" ] }
|
||||||
argon2 = "0.5"
|
argon2 = "0.5"
|
||||||
bitflags = { version = "2.8", features = [ "serde" ] }
|
|
||||||
|
|
||||||
|
|
||||||
# Tertiary crates
|
# Tertiary crates
|
||||||
|
@ -4,7 +4,7 @@ CREATE TABLE "members" (
|
|||||||
full_name text NOT NULL,
|
full_name text NOT NULL,
|
||||||
registration_token text NOT NULL UNIQUE,
|
registration_token text NOT NULL UNIQUE,
|
||||||
diploma text,
|
diploma text,
|
||||||
swim_groups bigint NOT NULL,
|
hours text[] NOT NULL,
|
||||||
groups bigint NOT NULL
|
groups text[] NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4,13 +4,8 @@ use argon2::{
|
|||||||
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
password_hash::{rand_core::OsRng, PasswordHasher, SaltString},
|
||||||
Argon2, PasswordHash, PasswordVerifier,
|
Argon2, PasswordHash, PasswordVerifier,
|
||||||
};
|
};
|
||||||
use axum::{
|
use axum::{extract::FromRequestParts, http::request::Parts, RequestPartsExt};
|
||||||
extract::FromRequestParts,
|
|
||||||
http::{request::Parts, StatusCode},
|
|
||||||
RequestPartsExt,
|
|
||||||
};
|
|
||||||
use axum_extra::{
|
use axum_extra::{
|
||||||
extract::cookie::{Cookie, CookieJar},
|
|
||||||
headers::{authorization::Bearer, Authorization},
|
headers::{authorization::Bearer, Authorization},
|
||||||
typed_header::TypedHeaderRejectionReason,
|
typed_header::TypedHeaderRejectionReason,
|
||||||
TypedHeader,
|
TypedHeader,
|
||||||
@ -22,11 +17,8 @@ use rand::prelude::*;
|
|||||||
use rand_chacha::ChaCha20Rng;
|
use rand_chacha::ChaCha20Rng;
|
||||||
use tokio::task;
|
use tokio::task;
|
||||||
|
|
||||||
use crate::database::model::User;
|
|
||||||
|
|
||||||
mod bearer;
|
mod bearer;
|
||||||
mod error;
|
mod error;
|
||||||
mod scopes;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Permissions<'a>(pub HashSet<&'a str>);
|
pub struct Permissions<'a>(pub HashSet<&'a str>);
|
||||||
@ -59,16 +51,6 @@ where
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
match parts.extract::<CookieJar>().await {
|
|
||||||
Ok(jar) => {
|
|
||||||
if let Some(session_token) = jar.get("session_token") {
|
|
||||||
// TODO: Implement function to retrieve user permissions
|
|
||||||
tracing::info!("{session_token:?}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(_) => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
Err(AuthError::Unauthorized.into())
|
Err(AuthError::Unauthorized.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
use crate::bitflags_serde_impl;
|
|
||||||
use bitflags::bitflags;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
|
||||||
pub struct Scopes: u64 {
|
|
||||||
const USER_READ = 1 << 0;
|
|
||||||
const USER_WRITE = 1 << 1;
|
|
||||||
const USER_DELETE = 1 << 2;
|
|
||||||
|
|
||||||
const MEMBER_CREATE = 1 << 3;
|
|
||||||
const MEMBER_READ = 1 << 4;
|
|
||||||
const MEMBER_WRITE = 1 << 5;
|
|
||||||
const MEMBER_DELETE = 1 << 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bitflags_serde_impl!(Scopes, u64);
|
|
@ -2,8 +2,6 @@ use rand::distr::{Alphanumeric, SampleString};
|
|||||||
use sqlx::{PgPool, Postgres, QueryBuilder};
|
use sqlx::{PgPool, Postgres, QueryBuilder};
|
||||||
use validator::Validate;
|
use validator::Validate;
|
||||||
|
|
||||||
use crate::model::member::{Groups, SwimGroups};
|
|
||||||
|
|
||||||
#[derive(Debug, Validate, sqlx::FromRow)]
|
#[derive(Debug, Validate, sqlx::FromRow)]
|
||||||
pub struct Member {
|
pub struct Member {
|
||||||
#[validate(length(equal = 7))]
|
#[validate(length(equal = 7))]
|
||||||
@ -12,22 +10,40 @@ pub struct Member {
|
|||||||
pub full_name: String,
|
pub full_name: String,
|
||||||
pub registration_token: Option<String>,
|
pub registration_token: Option<String>,
|
||||||
pub diploma: Option<String>,
|
pub diploma: Option<String>,
|
||||||
pub swim_groups: SwimGroups,
|
pub hours: Vec<String>,
|
||||||
pub groups: Groups,
|
pub groups: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SearchMember {
|
||||||
|
pub registration_tokens: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Member {
|
impl Member {
|
||||||
pub async fn get_many_from_registration_tokens(
|
pub async fn search(
|
||||||
pool: &PgPool,
|
transaction: &PgPool,
|
||||||
registration_tokens: Vec<String>,
|
search: SearchMember,
|
||||||
) -> Result<Vec<Self>, sqlx::Error> {
|
) -> Result<Vec<Self>, sqlx::Error> {
|
||||||
let members = sqlx::query_as!(
|
if let None = search.registration_tokens {
|
||||||
Member,
|
return Err(sqlx::Error::RowNotFound);
|
||||||
"SELECT * FROM members WHERE registration_token = ANY($1);",
|
}
|
||||||
®istration_tokens
|
|
||||||
)
|
let mut query = QueryBuilder::new("SELECT * from members WHERE 1=1");
|
||||||
.fetch_all(pool)
|
|
||||||
.await?;
|
if let Some(registration_tokens) = search.registration_tokens {
|
||||||
|
if registration_tokens.len() == 0 {
|
||||||
|
return Err(sqlx::Error::RowNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
query.push(" AND registration_token = ANY(");
|
||||||
|
query.push_bind(registration_tokens);
|
||||||
|
query.push(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
let members: Vec<Self> = query.build_query_as().fetch_all(transaction).await?;
|
||||||
|
|
||||||
|
if members.len() == 0 {
|
||||||
|
return Err(sqlx::Error::RowNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(members)
|
Ok(members)
|
||||||
}
|
}
|
||||||
@ -53,7 +69,7 @@ impl Member {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut query_builder = QueryBuilder::new(
|
let mut query_builder = QueryBuilder::new(
|
||||||
"INSERT INTO members(member_id, first_name, full_name, registration_token, diploma, swim_groups, groups) "
|
"INSERT INTO members(member_id, first_name, full_name, registration_token, diploma, hours, groups) "
|
||||||
);
|
);
|
||||||
|
|
||||||
query_builder.push_values(members.into_iter(), |mut b, member| {
|
query_builder.push_values(members.into_iter(), |mut b, member| {
|
||||||
@ -64,8 +80,8 @@ impl Member {
|
|||||||
b.push_bind(member.full_name);
|
b.push_bind(member.full_name);
|
||||||
b.push_bind(registration_token);
|
b.push_bind(registration_token);
|
||||||
b.push_bind(member.diploma);
|
b.push_bind(member.diploma);
|
||||||
b.push_bind(member.swim_groups.bits() as i64);
|
b.push_bind(member.hours);
|
||||||
b.push_bind(member.groups.bits() as i64);
|
b.push_bind(member.groups);
|
||||||
});
|
});
|
||||||
|
|
||||||
let query = query_builder.build();
|
let query = query_builder.build();
|
||||||
@ -83,21 +99,7 @@ impl Member {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for member in members {
|
for member in members {
|
||||||
sqlx::query!(
|
sqlx::query!("UPDATE ONLY members SET first_name = $1, full_name = $2, diploma = $3, hours = $4, groups = $5 WHERE member_id = $6", member.first_name, member.full_name, member.diploma, &member.hours, &member.groups, member.member_id).execute(&mut **transaction).await?;
|
||||||
"
|
|
||||||
UPDATE ONLY members
|
|
||||||
SET first_name = $1, full_name = $2, diploma = $3, swim_groups = $4, groups = $5
|
|
||||||
WHERE member_id = $6
|
|
||||||
",
|
|
||||||
member.first_name,
|
|
||||||
member.full_name,
|
|
||||||
member.diploma,
|
|
||||||
member.swim_groups.bits() as i64,
|
|
||||||
member.groups.bits() as i64,
|
|
||||||
member.member_id
|
|
||||||
)
|
|
||||||
.execute(&mut **transaction)
|
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use sqlx::{PgPool, Postgres};
|
use sqlx::Postgres;
|
||||||
|
|
||||||
pub struct Session {
|
pub struct Session {
|
||||||
pub session_id: uuid::Uuid,
|
pub session_id: uuid::Uuid,
|
||||||
@ -34,12 +34,4 @@ impl Session {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn from_token(transaction: &PgPool, token: &str) -> Result<Self, sqlx::Error> {
|
|
||||||
let session = sqlx::query_as!(Self, "SELECT * FROM sessions WHERE token = $1;", token)
|
|
||||||
.fetch_one(transaction)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(session)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,91 +1,17 @@
|
|||||||
use bitflags::bitflags;
|
#[derive(Debug, Clone, serde::Serialize)]
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct Name {
|
pub struct Name {
|
||||||
pub first: String,
|
pub first: String,
|
||||||
pub full: String,
|
pub full: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, serde::Serialize)]
|
||||||
pub struct Member {
|
pub struct Member {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
pub registration_token: Option<String>,
|
pub registration_token: Option<String>,
|
||||||
pub diploma: Option<String>,
|
pub diploma: Option<String>,
|
||||||
pub swim_groups: SwimGroups,
|
pub hours: Vec<String>,
|
||||||
pub groups: Groups,
|
pub groups: Vec<String>,
|
||||||
}
|
|
||||||
|
|
||||||
bitflags! {
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct Groups: u64 {
|
|
||||||
const NONE = 1 << 0;
|
|
||||||
const KADER = 1 << 1;
|
|
||||||
const ZWEMZAKEN = 1 << 2;
|
|
||||||
const WEDSTRIJDEN = 1 << 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
|
||||||
pub struct SwimGroups: u64 {
|
|
||||||
const NONE = 1 << 0;
|
|
||||||
|
|
||||||
const A1 = 1 << 1;
|
|
||||||
const A2 = 1 << 2;
|
|
||||||
const A3 = 1 << 3;
|
|
||||||
const A4 = 1 << 4;
|
|
||||||
const A5 = 1 << 5;
|
|
||||||
const A6 = 1 << 6;
|
|
||||||
|
|
||||||
const B1 = 1 << 7;
|
|
||||||
const B2 = 1 << 8;
|
|
||||||
const B3 = 1 << 9;
|
|
||||||
const B4 = 1 << 10;
|
|
||||||
const B5 = 1 << 11;
|
|
||||||
const B6 = 1 << 12;
|
|
||||||
|
|
||||||
const C1 = 1 << 13;
|
|
||||||
const C2 = 1 << 14;
|
|
||||||
const C3 = 1 << 15;
|
|
||||||
const C4 = 1 << 16;
|
|
||||||
const C5 = 1 << 17;
|
|
||||||
const C6 = 1 << 18;
|
|
||||||
|
|
||||||
const D1 = 1 << 19;
|
|
||||||
const D2 = 1 << 20;
|
|
||||||
const D3 = 1 << 21;
|
|
||||||
const D4 = 1 << 22;
|
|
||||||
const D5 = 1 << 23;
|
|
||||||
const D6 = 1 << 24;
|
|
||||||
|
|
||||||
const E1 = 1 << 25;
|
|
||||||
const E2 = 1 << 26;
|
|
||||||
const E3 = 1 << 27;
|
|
||||||
const E4 = 1 << 28;
|
|
||||||
const E5 = 1 << 29;
|
|
||||||
const E6 = 1 << 30;
|
|
||||||
|
|
||||||
const Z1 = 1 << 31;
|
|
||||||
const Z2 = 1 << 32;
|
|
||||||
const Z3 = 1 << 33;
|
|
||||||
const Z4 = 1 << 34;
|
|
||||||
const Z5 = 1 << 35;
|
|
||||||
const Z6 = 1 << 36;
|
|
||||||
|
|
||||||
const WEDSTRIJD = 1 << 37;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<i64> for SwimGroups {
|
|
||||||
fn from(value: i64) -> Self {
|
|
||||||
Self::from_bits(value as u64).unwrap_or(SwimGroups::NONE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<i64> for Groups {
|
|
||||||
fn from(value: i64) -> Self {
|
|
||||||
Self::from_bits(value as u64).unwrap_or(Groups::NONE)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::database::model::Member as DbMember;
|
use crate::database::model::Member as DbMember;
|
||||||
@ -99,7 +25,7 @@ impl From<DbMember> for Member {
|
|||||||
},
|
},
|
||||||
registration_token: value.registration_token,
|
registration_token: value.registration_token,
|
||||||
diploma: value.diploma,
|
diploma: value.diploma,
|
||||||
swim_groups: value.swim_groups,
|
hours: value.hours,
|
||||||
groups: value.groups,
|
groups: value.groups,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,7 +39,7 @@ impl From<Member> for DbMember {
|
|||||||
full_name: value.name.full,
|
full_name: value.name.full,
|
||||||
registration_token: None,
|
registration_token: None,
|
||||||
diploma: value.diploma,
|
diploma: value.diploma,
|
||||||
swim_groups: value.swim_groups,
|
hours: value.hours,
|
||||||
groups: value.groups,
|
groups: value.groups,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use axum::{extract::State, routing::post, Json, Router};
|
use axum::{extract::State, routing::post, Json, Router};
|
||||||
|
|
||||||
use crate::auth::verify_password_hash;
|
use crate::auth::verify_password_hash;
|
||||||
|
use crate::database::model::member::SearchMember;
|
||||||
use crate::database::model::Member as DbMember;
|
use crate::database::model::Member as DbMember;
|
||||||
use crate::database::model::Session as DbSession;
|
use crate::database::model::Session as DbSession;
|
||||||
use crate::database::model::User as DbUser;
|
use crate::database::model::User as DbUser;
|
||||||
@ -54,8 +55,12 @@ pub async fn register<'a>(
|
|||||||
Json(auth_request): Json<RegisterRequest>,
|
Json(auth_request): Json<RegisterRequest>,
|
||||||
) -> Result<String, crate::Error> {
|
) -> Result<String, crate::Error> {
|
||||||
// Get all the members to link with the user
|
// Get all the members to link with the user
|
||||||
let members =
|
let members = DbMember::search(
|
||||||
DbMember::get_many_from_registration_tokens(&state.pool, auth_request.registration_tokens)
|
&state.pool,
|
||||||
|
SearchMember {
|
||||||
|
registration_tokens: Some(auth_request.registration_tokens),
|
||||||
|
},
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let member_ids: Vec<String> = members.into_iter().map(|m| m.member_id).collect();
|
let member_ids: Vec<String> = members.into_iter().map(|m| m.member_id).collect();
|
||||||
|
@ -10,10 +10,7 @@ use sqlx::PgPool;
|
|||||||
use crate::{
|
use crate::{
|
||||||
auth::{AuthError, Permissions},
|
auth::{AuthError, Permissions},
|
||||||
database::model::Member as DbMember,
|
database::model::Member as DbMember,
|
||||||
model::{
|
model::{member::Name, Member},
|
||||||
member::{Groups, Name, SwimGroups},
|
|
||||||
Member,
|
|
||||||
},
|
|
||||||
util::convert_vec,
|
util::convert_vec,
|
||||||
AppState,
|
AppState,
|
||||||
};
|
};
|
||||||
@ -119,7 +116,7 @@ struct Row {
|
|||||||
#[serde(rename = "E-mail")]
|
#[serde(rename = "E-mail")]
|
||||||
email: String,
|
email: String,
|
||||||
#[serde(rename = "Verenigingssporten")]
|
#[serde(rename = "Verenigingssporten")]
|
||||||
swim_groups: String,
|
hours: String,
|
||||||
#[serde(rename = "Diploma dropdown 1")]
|
#[serde(rename = "Diploma dropdown 1")]
|
||||||
diploma: Option<String>,
|
diploma: Option<String>,
|
||||||
}
|
}
|
||||||
@ -164,22 +161,22 @@ impl Row {
|
|||||||
members
|
members
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swim_groups_parsed(&self) -> SwimGroups {
|
fn hours_parsed(&self) -> Vec<String> {
|
||||||
let mut swim_groups: Vec<String> = Vec::new();
|
let mut hours: Vec<String> = Vec::new();
|
||||||
|
|
||||||
let group_parts: Vec<&str> = self.swim_groups.split(", ").collect();
|
let group_parts: Vec<&str> = self.hours.split(", ").collect();
|
||||||
|
|
||||||
for group in group_parts {
|
for group in group_parts {
|
||||||
let hour_parts: Vec<&str> = group.split(" - ").collect();
|
let hour_parts: Vec<&str> = group.split(" - ").collect();
|
||||||
|
|
||||||
if let Some(group) = hour_parts.get(1) {
|
for part in hour_parts {
|
||||||
swim_groups.push(group.to_uppercase())
|
if &*part != "Groep" {
|
||||||
|
hours.push(part.to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let swim_groups_string = swim_groups.join("|");
|
hours.into_iter().unique().collect()
|
||||||
|
|
||||||
bitflags::parser::from_str(&swim_groups_string).unwrap_or(SwimGroups::empty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,8 +198,8 @@ impl Into<Member> for Row {
|
|||||||
name,
|
name,
|
||||||
registration_token: None,
|
registration_token: None,
|
||||||
diploma: self.diploma.clone(),
|
diploma: self.diploma.clone(),
|
||||||
swim_groups: self.swim_groups_parsed(),
|
hours: self.hours_parsed(),
|
||||||
groups: Groups::empty(),
|
groups: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -264,7 +261,7 @@ fn generate_diff(members_new: Vec<Member>, members_old: Vec<Member>) -> MembersD
|
|||||||
name: new_member.name.clone(),
|
name: new_member.name.clone(),
|
||||||
registration_token: old_member.registration_token,
|
registration_token: old_member.registration_token,
|
||||||
diploma: new_member.diploma.clone(),
|
diploma: new_member.diploma.clone(),
|
||||||
swim_groups: new_member.swim_groups.clone(),
|
hours: new_member.hours.clone(),
|
||||||
groups: old_member.groups,
|
groups: old_member.groups,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
mod bitflags;
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
|
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
#[macro_export]
|
|
||||||
macro_rules! bitflags_serde_impl {
|
|
||||||
($type:ident, $int_type:ident) => {
|
|
||||||
impl serde::Serialize for $type {
|
|
||||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
|
||||||
serializer.serialize_i64(self.bits() as i64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> serde::Deserialize<'de> for $type {
|
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
|
||||||
let v: i64 = Deserialize::deserialize(deserializer)?;
|
|
||||||
|
|
||||||
Ok($type::from_bits_truncate(v as $int_type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -39,7 +39,7 @@ impl IntoResponse for Error {
|
|||||||
fn into_response(self) -> Response {
|
fn into_response(self) -> Response {
|
||||||
let (status_code, code) = match self {
|
let (status_code, code) = match self {
|
||||||
Self::Sqlx(ref err_kind) => match err_kind {
|
Self::Sqlx(ref err_kind) => match err_kind {
|
||||||
sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, "DATABASE_ROW_NOT_FOUND"),
|
sqlx::Error::RowNotFound => (StatusCode::NOT_FOUND, "DATABSE_ROW_NOT_FOUND"),
|
||||||
_ => (StatusCode::INTERNAL_SERVER_ERROR, "DATABASE_ERROR"),
|
_ => (StatusCode::INTERNAL_SERVER_ERROR, "DATABASE_ERROR"),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user