Basic template
This commit is contained in:
commit
f3d4da17e5
16 changed files with 3305 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/target
|
||||
|
||||
/certs
|
||||
Caddyfile
|
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
11
.idea/matrixdiscord.iml
generated
Normal file
11
.idea/matrixdiscord.iml
generated
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="CPP_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/matrixdiscord.iml" filepath="$PROJECT_DIR$/.idea/matrixdiscord.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
3036
Cargo.lock
generated
Normal file
3036
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
25
Cargo.toml
Normal file
25
Cargo.toml
Normal file
|
@ -0,0 +1,25 @@
|
|||
[package]
|
||||
name = "matrixdiscord"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
## Core
|
||||
tokio = { version = "1.26.0", features = ["full"] }
|
||||
|
||||
## Web
|
||||
axum = "^0.6"
|
||||
tower-http = { version = "*", features = ["cors"] }
|
||||
|
||||
## json citrus
|
||||
serde = { version = "1.0.156", features = ["derive"] }
|
||||
serde_derive = "1.0.156"
|
||||
serde_json = "1.0.94"
|
||||
serde_with = "2.3.1"
|
||||
|
||||
## Misc
|
||||
tracing = "0.1.37"
|
||||
tracing-subscriber = "0.3.16"
|
||||
matrix-sdk = "0.6.2"
|
1
src/gateway/mod.rs
Normal file
1
src/gateway/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
mod routes;
|
1
src/gateway/routes/mod.rs
Normal file
1
src/gateway/routes/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
|
1
src/http/mod.rs
Normal file
1
src/http/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod v9;
|
111
src/http/v9/errors.rs
Normal file
111
src/http/v9/errors.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use axum::http::StatusCode;
|
||||
use axum::Json;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_with::{serde_as, DisplayFromStr};
|
||||
|
||||
pub async fn throw_http_error(
|
||||
error: APIErrorCode,
|
||||
error_messages: Vec<APIErrorField>,
|
||||
) -> Json<APIError> {
|
||||
// I really don't like doing this, maybe play around with serde_as more
|
||||
let mut error_messages_vec = Vec::<(String, APIErrorField)>::new();
|
||||
|
||||
for i in error_messages {
|
||||
error_messages_vec.push((String::from(i.clone()), i));
|
||||
}
|
||||
|
||||
Json(APIError {
|
||||
code: u16::from(error),
|
||||
message: String::from(error),
|
||||
errors: error_messages_vec,
|
||||
})
|
||||
}
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct APIError {
|
||||
code: u16,
|
||||
message: String,
|
||||
#[serde_as(as = "HashMap<DisplayFromStr, _>")]
|
||||
errors: Vec<(String, APIErrorField)>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum APIErrorField {
|
||||
#[serde(alias = "password")]
|
||||
Password { _errors: Vec<APIErrorMessage> },
|
||||
#[serde(alias = "username")]
|
||||
Username { _errors: Vec<APIErrorMessage> },
|
||||
#[serde(alias = "login")]
|
||||
Login { _errors: Vec<APIErrorMessage> },
|
||||
#[serde(alias = "email")]
|
||||
Email { _errors: Vec<APIErrorMessage> },
|
||||
#[serde(alias = "date_of_birth")]
|
||||
DateOfBirth { _errors: Vec<APIErrorMessage> },
|
||||
}
|
||||
|
||||
impl From<APIErrorField> for String {
|
||||
fn from(field: APIErrorField) -> String {
|
||||
match field {
|
||||
APIErrorField::Password { .. } => "password",
|
||||
APIErrorField::Username { .. } => "username",
|
||||
APIErrorField::Login { .. } => "login",
|
||||
APIErrorField::Email { .. } => "email",
|
||||
APIErrorField::DateOfBirth { .. } => "date_of_birth",
|
||||
}
|
||||
.parse()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Hash)]
|
||||
pub struct APIErrorMessage {
|
||||
pub(crate) code: String,
|
||||
pub(crate) message: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
|
||||
pub enum APIErrorCode {
|
||||
UnknownAccount,
|
||||
Unauthorized,
|
||||
InvalidFormBody,
|
||||
}
|
||||
|
||||
impl From<APIErrorCode> for u16 {
|
||||
fn from(code: APIErrorCode) -> u16 {
|
||||
match code {
|
||||
APIErrorCode::UnknownAccount => 10001,
|
||||
APIErrorCode::Unauthorized => 40001,
|
||||
APIErrorCode::InvalidFormBody => 50035,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<APIErrorCode> for String {
|
||||
fn from(code: APIErrorCode) -> String {
|
||||
match code {
|
||||
APIErrorCode::UnknownAccount => "Unknown Account".to_string(),
|
||||
APIErrorCode::Unauthorized => "Unauthorized".to_string(),
|
||||
APIErrorCode::InvalidFormBody => "Unknown Form Body".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<APIErrorCode> for StatusCode {
|
||||
fn from(code: APIErrorCode) -> StatusCode {
|
||||
match code {
|
||||
APIErrorCode::UnknownAccount => StatusCode::BAD_REQUEST,
|
||||
APIErrorCode::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
APIErrorCode::InvalidFormBody => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'t> From<&'t APIErrorCode> for u16 {
|
||||
fn from(code: &'t APIErrorCode) -> u16 {
|
||||
(*code).into()
|
||||
}
|
||||
}
|
2
src/http/v9/mod.rs
Normal file
2
src/http/v9/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
|||
pub mod errors;
|
||||
pub mod routes;
|
17
src/http/v9/routes/auth.rs
Normal file
17
src/http/v9/routes/auth.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use axum::Json;
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LoginReq {
|
||||
pub login: String,
|
||||
pub password: String
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LoginRes {
|
||||
pub token: String
|
||||
}
|
||||
|
||||
pub async fn login(Json(payload): Json<LoginReq>) -> Json<LoginRes> {
|
||||
Json(LoginRes { token: "".to_string() })
|
||||
}
|
20
src/http/v9/routes/mod.rs
Normal file
20
src/http/v9/routes/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
use axum::{Router, routing::{get, post}};
|
||||
use crate::http::v9::routes::auth::login;
|
||||
|
||||
use crate::http::v9::routes::tracking::*;
|
||||
|
||||
pub mod auth;
|
||||
pub mod tracking;
|
||||
|
||||
pub fn assemble_routes() -> Router {
|
||||
let auth = Router::new()
|
||||
.route("/login", post(login));
|
||||
|
||||
Router::new()
|
||||
.nest("/auth", auth)
|
||||
|
||||
.route("/experiments", get(experiments))
|
||||
|
||||
.route("/science", post(science))
|
||||
.route("/track", post(science))
|
||||
}
|
16
src/http/v9/routes/tracking.rs
Normal file
16
src/http/v9/routes/tracking.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
use axum::Json;
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Experiments {
|
||||
pub fingerprint: String,
|
||||
pub assignments: Vec<[i32; 5]>
|
||||
}
|
||||
|
||||
pub async fn experiments() -> Json<Experiments> {
|
||||
Json(Experiments { fingerprint: "big balls".to_string(), assignments: vec![] })
|
||||
}
|
||||
|
||||
pub async fn science() -> &'static str {
|
||||
"yummy i love user data"
|
||||
}
|
38
src/main.rs
Normal file
38
src/main.rs
Normal file
|
@ -0,0 +1,38 @@
|
|||
use axum::{Router};
|
||||
use std::net::SocketAddr;
|
||||
use axum::http::Method;
|
||||
use axum::routing::get;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
|
||||
mod gateway;
|
||||
mod http;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
tracing_subscriber::fmt::init();
|
||||
|
||||
tracing::info!("Starting matrixdiscord");
|
||||
|
||||
// CORS
|
||||
let cors = CorsLayer::new()
|
||||
.allow_origin(Any)
|
||||
.allow_methods([Method::GET, Method::POST, Method::PATCH, Method::OPTIONS])
|
||||
.allow_headers(Any);
|
||||
|
||||
let api = Router::new()
|
||||
.nest("/v9", http::v9::routes::assemble_routes());
|
||||
|
||||
let app = Router::new()
|
||||
.nest("/api", api)
|
||||
.layer(cors)
|
||||
|
||||
.route("/", get(|| async { "?" }));
|
||||
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 4200));
|
||||
tracing::info!("Listening on {}", addr);
|
||||
|
||||
axum::Server::bind(&addr)
|
||||
.serve(app.into_make_service())
|
||||
.await
|
||||
.expect("Waaa");
|
||||
}
|
Loading…
Add table
Reference in a new issue