✨ Some basic rust code for new backend
This commit is contained in:
@@ -12,3 +12,4 @@ node_modules/
|
|||||||
survey.json
|
survey.json
|
||||||
.coverage
|
.coverage
|
||||||
export_deta.py
|
export_deta.py
|
||||||
|
target/
|
||||||
|
|||||||
Generated
+2337
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
|||||||
|
SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MPL-2.0
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
members = ["app", "live", "shared"]
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
sqlx = { version = "0.7", features = [
|
||||||
|
"runtime-tokio",
|
||||||
|
"postgres",
|
||||||
|
"uuid",
|
||||||
|
"chrono",
|
||||||
|
"json",
|
||||||
|
"macros",
|
||||||
|
"migrate",
|
||||||
|
] }
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = { version = "1", features = ["raw_value"] }
|
||||||
|
tokio = { version = "1.36", features = ["full"] }
|
||||||
|
chrono = { version = "0.4", features = ["clock", "serde"] }
|
||||||
|
dotenvy = "0.15"
|
||||||
|
uuid = { version = "1.7.0", features = ["serde", "v4", "fast-rng", "v7"] }
|
||||||
|
anyhow = "1"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "app"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
[package]
|
||||||
|
name = "live"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
[package]
|
||||||
|
name = "shared"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
|
sqlx = { workspace = true }
|
||||||
|
serde = { workspace = true }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
uuid = { workspace = true }
|
||||||
|
chrono = { workspace = true }
|
||||||
|
validator = { version = "0.18", features = ["derive"] }
|
||||||
|
garde = { version = "0.20", features = ["full"] }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
pub mod models;
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
use garde::{Validate, Valid};
|
||||||
|
|
||||||
|
#[derive(strum::Display)]
|
||||||
|
#[strum(serialize_all = "UPPERCASE")]
|
||||||
|
pub enum UserAuthTypes {
|
||||||
|
Local,
|
||||||
|
Google,
|
||||||
|
Github,
|
||||||
|
Custom,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct User {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub email: String,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub verified: bool,
|
||||||
|
pub verify_key: Option<String>,
|
||||||
|
pub created_at: chrono::NaiveDateTime,
|
||||||
|
pub auth_type: UserAuthTypes,
|
||||||
|
pub google_uid: Option<String>,
|
||||||
|
pub avatar: Vec<u8>,
|
||||||
|
pub github_user_id: Option<i32>,
|
||||||
|
pub require_password: bool,
|
||||||
|
pub backup_code: String,
|
||||||
|
pub totp_secret: String,
|
||||||
|
pub storage_used: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FidoCredentials {
|
||||||
|
pub pk: i32,
|
||||||
|
pub id: Vec<u8>,
|
||||||
|
pub public_key: Vec<u8>,
|
||||||
|
pub sign_count: i32,
|
||||||
|
pub user: Uuid,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ApiKey {
|
||||||
|
pub key: String,
|
||||||
|
pub user: Option<Uuid>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UserSession {
|
||||||
|
pub id: Uuid,
|
||||||
|
pub user: Option<Uuid>,
|
||||||
|
pub session_key: String,
|
||||||
|
pub created_at: chrono::NaiveDateTime,
|
||||||
|
pub ip_address: String,
|
||||||
|
pub user_agent: String,
|
||||||
|
pub last_seen: chrono::NaiveDateTime,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct ABCDQuizAnswer {
|
||||||
|
right: bool,
|
||||||
|
answer: String,
|
||||||
|
color: Option<String>,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct RangeQuizAnswer {
|
||||||
|
min: i32,
|
||||||
|
max: i32,
|
||||||
|
min_correct: i32,
|
||||||
|
max_correct: i32,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct VotingQuizAnswer {
|
||||||
|
answer: String,
|
||||||
|
image: Option<String>,
|
||||||
|
color: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(strum::Display, Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
|
#[strum(serialize_all = "UPPERCASE")]
|
||||||
|
pub enum QuizQuestionType {
|
||||||
|
Abcd,
|
||||||
|
Range,
|
||||||
|
Voting,
|
||||||
|
Slide,
|
||||||
|
Text,
|
||||||
|
Order,
|
||||||
|
Check,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct TextQuizAnswer {
|
||||||
|
answer: String,
|
||||||
|
case_sensitive: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Validate)]
|
||||||
|
pub struct QuizQuestion {
|
||||||
|
#[garde(skip)]
|
||||||
|
question: String,
|
||||||
|
#[garde(skip)]
|
||||||
|
time: i32,
|
||||||
|
#[serde(default = "default_type")]
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
#[garde(skip)]
|
||||||
|
question_type: Option<QuizQuestionType>,
|
||||||
|
#[garde(custom(validate_answers))]
|
||||||
|
answers: QuizAnswers,
|
||||||
|
#[garde(skip)]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
image: Option<String>,
|
||||||
|
#[garde(skip)]
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
hide_results: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
enum QuizAnswers {
|
||||||
|
ABCD(Vec<ABCDQuizAnswer>),
|
||||||
|
Range(RangeQuizAnswer),
|
||||||
|
Text(Vec<TextQuizAnswer>),
|
||||||
|
Voting(Vec<VotingQuizAnswer>),
|
||||||
|
Slide(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_type() -> Option<QuizQuestionType> {
|
||||||
|
Some(QuizQuestionType::Abcd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl Validate for QuizQuestion {
|
||||||
|
// fn validate(&self) -> Result<(), ValidationErrors> {
|
||||||
|
// match validate_answers(&self.answers, self) {
|
||||||
|
// Ok(_) => Ok(()),
|
||||||
|
// Err(e) => {
|
||||||
|
// let mut error = ValidationErrors::new();
|
||||||
|
// error.add("answers", e);
|
||||||
|
// Err(error)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn validate_answers(answers: &QuizAnswers) -> garde::Result {
|
||||||
|
match (&context.question_type, answers) {
|
||||||
|
(Some(QuizQuestionType::Abcd), QuizAnswers::ABCD(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Range), QuizAnswers::Range(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Voting), QuizAnswers::Voting(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Text), QuizAnswers::Text(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Order), QuizAnswers::Voting(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Slide), QuizAnswers::Slide(_)) => Ok(()),
|
||||||
|
(Some(QuizQuestionType::Check), QuizAnswers::ABCD(_)) => Ok(()),
|
||||||
|
_ => Err(garde::Error::new("invalid_answers")),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<!--
|
||||||
|
SPDX-FileCopyrightText: 2023 Marlon W (Mawoka)
|
||||||
|
|
||||||
|
SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Migration of the Backend to Rust (long term goal)
|
||||||
Reference in New Issue
Block a user