style: cargo fmt & clippy fixes
All checks were successful
ci/woodpecker/push/build-and-publish Pipeline was successful

This commit is contained in:
Radical 2025-07-20 16:30:46 +02:00
parent 969b517e18
commit a602c2624f
29 changed files with 216 additions and 86 deletions

View file

@ -2,7 +2,7 @@
use std::sync::Arc;
use axum::{routing::get, Router};
use axum::{Router, routing::get};
use crate::AppState;

View file

@ -2,14 +2,17 @@
use std::sync::Arc;
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension, Json};
use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse};
use diesel::{ExpressionMethods, QueryDsl, Queryable, Selectable, SelectableHelper};
use diesel_async::RunQueryDsl;
use serde::Serialize;
use uuid::Uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, schema::refresh_tokens::{self, dsl}, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
schema::refresh_tokens::{self, dsl},
};
#[derive(Serialize, Selectable, Queryable)]

View file

@ -20,8 +20,8 @@ use crate::{
error::Error,
schema::*,
utils::{
PASSWORD_REGEX, generate_token, new_refresh_token_cookie,
user_uuid_from_identifier, generate_device_name
PASSWORD_REGEX, generate_device_name, generate_token, new_refresh_token_cookie,
user_uuid_from_identifier,
},
};
@ -95,7 +95,14 @@ pub async fn response(
.execute(&mut conn)
.await?;
let mut response = (StatusCode::OK, Json(Response { access_token, device_name })).into_response();
let mut response = (
StatusCode::OK,
Json(Response {
access_token,
device_name,
}),
)
.into_response();
response.headers_mut().append(
"Set-Cookie",

View file

@ -4,9 +4,16 @@ use std::{
};
use axum::{
extract::{Request, State}, middleware::{from_fn_with_state, Next}, response::IntoResponse, routing::{delete, get, post}, Router
Router,
extract::{Request, State},
middleware::{Next, from_fn_with_state},
response::IntoResponse,
routing::{delete, get, post},
};
use axum_extra::{
TypedHeader,
headers::{Authorization, authorization::Bearer},
};
use axum_extra::{headers::{authorization::Bearer, Authorization}, TypedHeader};
use diesel::{ExpressionMethods, QueryDsl};
use diesel_async::RunQueryDsl;
use serde::Serialize;
@ -23,14 +30,12 @@ mod reset_password;
mod revoke;
mod verify_email;
#[derive(Serialize)]
pub struct Response {
access_token: String,
device_name: String,
}
pub fn router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
let router_with_auth = Router::new()
.route("/verify-email", get(verify_email::get))
@ -82,9 +87,10 @@ impl CurrentUser<Uuid> {
State(app_state): State<Arc<AppState>>,
TypedHeader(auth): TypedHeader<Authorization<Bearer>>,
mut req: Request,
next: Next
next: Next,
) -> Result<impl IntoResponse, Error> {
let current_user = CurrentUser(check_access_token(auth.token(), &mut app_state.pool.get().await?).await?);
let current_user =
CurrentUser(check_access_token(auth.token(), &mut app_state.pool.get().await?).await?);
req.extensions_mut().insert(current_user);
Ok(next.run(req).await)

View file

@ -1,7 +1,8 @@
use axum::{
Json,
extract::State,
http::{HeaderValue, StatusCode},
response::IntoResponse, Json,
response::IntoResponse,
};
use axum_extra::extract::CookieJar;
use diesel::{ExpressionMethods, QueryDsl, delete, update};
@ -19,7 +20,8 @@ use crate::{
schema::{
access_tokens::{self, dsl},
refresh_tokens::{self, dsl as rdsl},
}, utils::{generate_token, new_refresh_token_cookie}
},
utils::{generate_token, new_refresh_token_cookie},
};
pub async fn post(
@ -104,7 +106,14 @@ pub async fn post(
.execute(&mut conn)
.await?;
let mut response = (StatusCode::OK, Json(Response { access_token, device_name })).into_response();
let mut response = (
StatusCode::OK,
Json(Response {
access_token,
device_name,
}),
)
.into_response();
// TODO: Dont set this when refresh token is unchanged
response.headers_mut().append(
@ -113,7 +122,6 @@ pub async fn post(
&new_refresh_token_cookie(&app_state.config, refresh_token).to_string(),
)?,
);
return Ok(response);
}

View file

@ -29,8 +29,8 @@ use crate::{
users::{self, dsl as udsl},
},
utils::{
EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX, generate_token,
new_refresh_token_cookie, generate_device_name
EMAIL_REGEX, PASSWORD_REGEX, USERNAME_REGEX, generate_device_name, generate_token,
new_refresh_token_cookie,
},
};
@ -137,11 +137,11 @@ pub async fn post(
let current_time = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
let device_name = generate_device_name();
insert_into(refresh_tokens::table)
.values((
rdsl::token.eq(&refresh_token),
rdsl::uuid.eq(uuid),
.values((
rdsl::token.eq(&refresh_token),
rdsl::uuid.eq(uuid),
rdsl::created_at.eq(current_time),
rdsl::device_name.eq(&device_name),
))
@ -162,7 +162,14 @@ pub async fn post(
Member::new(&app_state, uuid, initial_guild).await?;
}
let mut response = (StatusCode::OK, Json(Response {access_token, device_name})).into_response();
let mut response = (
StatusCode::OK,
Json(Response {
access_token,
device_name,
}),
)
.into_response();
response.headers_mut().append(
"Set-Cookie",

View file

@ -1,14 +1,20 @@
use std::sync::Arc;
use argon2::{PasswordHash, PasswordVerifier};
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension, Json};
use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse};
use diesel::{ExpressionMethods, QueryDsl, delete};
use diesel_async::RunQueryDsl;
use serde::Deserialize;
use uuid::Uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, schema::{refresh_tokens::{self, dsl as rdsl}, users::dsl as udsl}, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
schema::{
refresh_tokens::{self, dsl as rdsl},
users::dsl as udsl,
},
};
#[derive(Deserialize)]

View file

@ -3,16 +3,20 @@
use std::sync::Arc;
use axum::{
Extension,
extract::{Query, State},
http::StatusCode,
response::IntoResponse, Extension,
response::IntoResponse,
};
use chrono::{Duration, Utc};
use serde::Deserialize;
use uuid::Uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{EmailToken, Me}, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{EmailToken, Me},
};
#[derive(Deserialize)]
@ -41,7 +45,7 @@ pub struct QueryParams {
pub async fn get(
State(app_state): State<Arc<AppState>>,
Query(query): Query<QueryParams>,
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>,
) -> Result<impl IntoResponse, Error> {
let mut conn = app_state.pool.get().await?;
@ -79,7 +83,7 @@ pub async fn get(
///
pub async fn post(
State(app_state): State<Arc<AppState>>,
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>,
) -> Result<impl IntoResponse, Error> {
let me = Me::get(&mut app_state.pool.get().await?, uuid).await?;

View file

@ -3,11 +3,18 @@
use std::sync::Arc;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{Channel, Member}, utils::global_checks, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{Channel, Member},
utils::global_checks,
};
use ::uuid::Uuid;
use axum::{
extract::{Path, Query, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, Query, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;

View file

@ -13,7 +13,10 @@ use crate::{
utils::global_checks,
};
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;
@ -42,7 +45,9 @@ pub async fn delete(
let channel = Channel::fetch_one(&app_state, channel_uuid).await?;
let member = Member::check_membership(&mut app_state.pool.get().await?, uuid, channel.guild_uuid).await?;
let member =
Member::check_membership(&mut app_state.pool.get().await?, uuid, channel.guild_uuid)
.await?;
member
.check_permission(&app_state, Permissions::ManageChannel)
@ -101,7 +106,9 @@ pub async fn patch(
let mut channel = Channel::fetch_one(&app_state, channel_uuid).await?;
let member = Member::check_membership(&mut app_state.pool.get().await?, uuid, channel.guild_uuid).await?;
let member =
Member::check_membership(&mut app_state.pool.get().await?, uuid, channel.guild_uuid)
.await?;
member
.check_permission(&app_state, Permissions::ManageChannel)

View file

@ -2,16 +2,24 @@
use std::sync::Arc;
use ::uuid::Uuid;
use axum::{
extract::State, http::StatusCode, response::IntoResponse, routing::{get, post}, Extension, Json, Router
Extension, Json, Router,
extract::State,
http::StatusCode,
response::IntoResponse,
routing::{get, post},
};
use serde::Deserialize;
use ::uuid::Uuid;
mod uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{Guild, StartAmountQuery}, utils::global_checks, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{Guild, StartAmountQuery},
utils::global_checks,
};
#[derive(Deserialize)]
@ -55,7 +63,12 @@ pub async fn new(
Extension(CurrentUser(uuid)): Extension<CurrentUser<Uuid>>,
Json(guild_info): Json<GuildInfo>,
) -> Result<impl IntoResponse, Error> {
let guild = Guild::new(&mut app_state.pool.get().await?, guild_info.name.clone(), uuid).await?;
let guild = Guild::new(
&mut app_state.pool.get().await?,
guild_info.name.clone(),
uuid,
)
.await?;
Ok((StatusCode::OK, Json(guild)))
}

View file

@ -2,12 +2,19 @@ use std::sync::Arc;
use ::uuid::Uuid;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{Channel, Member, Permissions}, utils::{global_checks, order_by_is_above}, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{Channel, Member, Permissions},
utils::{global_checks, order_by_is_above},
};
#[derive(Deserialize)]
@ -55,7 +62,8 @@ pub async fn create(
) -> Result<impl IntoResponse, Error> {
global_checks(&app_state, uuid).await?;
let member = Member::check_membership(&mut app_state.pool.get().await?, uuid, guild_uuid).await?;
let member =
Member::check_membership(&mut app_state.pool.get().await?, uuid, guild_uuid).await?;
member
.check_permission(&app_state, Permissions::ManageChannel)

View file

@ -1,7 +1,10 @@
use std::sync::Arc;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;
use uuid::Uuid;

View file

@ -2,7 +2,10 @@ use std::sync::Arc;
use ::uuid::Uuid;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use crate::{

View file

@ -3,7 +3,11 @@
use std::sync::Arc;
use axum::{
extract::{Multipart, Path, State}, http::StatusCode, response::IntoResponse, routing::{get, patch, post}, Extension, Json, Router
Extension, Json, Router,
extract::{Multipart, Path, State},
http::StatusCode,
response::IntoResponse,
routing::{get, patch, post},
};
use bytes::Bytes;
use uuid::Uuid;

View file

@ -2,7 +2,10 @@ use std::sync::Arc;
use ::uuid::Uuid;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use serde::Deserialize;

View file

@ -2,7 +2,10 @@ use std::sync::Arc;
use ::uuid::Uuid;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use crate::{

View file

@ -1,7 +1,10 @@
use std::sync::Arc;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use uuid::Uuid;

View file

@ -1,13 +1,17 @@
use std::sync::Arc;
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension, Json};
use serde::Deserialize;
use ::uuid::Uuid;
use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse};
use serde::Deserialize;
pub mod uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::Me, utils::{global_checks, user_uuid_from_username}, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::Me,
utils::{global_checks, user_uuid_from_username},
};
/// Returns a list of users that are your friends

View file

@ -1,9 +1,10 @@
use std::sync::Arc;
use axum::{
Extension,
extract::{Path, State},
http::StatusCode,
response::IntoResponse, Extension,
response::IntoResponse,
};
use uuid::Uuid;

View file

@ -2,7 +2,7 @@
use std::sync::Arc;
use axum::{extract::State, http::StatusCode, response::IntoResponse, Extension, Json};
use axum::{Extension, Json, extract::State, http::StatusCode, response::IntoResponse};
use uuid::Uuid;
use crate::{

View file

@ -1,14 +1,18 @@
use std::sync::Arc;
use axum::{
extract::{DefaultBodyLimit, Multipart, State}, http::StatusCode, response::IntoResponse, routing::{delete, get, patch, post}, Extension, Json, Router
Extension, Json, Router,
extract::{DefaultBodyLimit, Multipart, State},
http::StatusCode,
response::IntoResponse,
routing::{delete, get, patch, post},
};
use bytes::Bytes;
use serde::Deserialize;
use uuid::Uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::Me, utils::global_checks, AppState
AppState, api::v1::auth::CurrentUser, error::Error, objects::Me, utils::global_checks,
};
mod friends;

View file

@ -2,9 +2,9 @@
use std::sync::Arc;
use axum::{middleware::from_fn_with_state, routing::get, Router};
use axum::{Router, middleware::from_fn_with_state, routing::get};
use crate::{api::v1::auth::CurrentUser, AppState};
use crate::{AppState, api::v1::auth::CurrentUser};
mod auth;
mod channels;
@ -21,7 +21,10 @@ pub fn router(app_state: Arc<AppState>) -> Router<Arc<AppState>> {
.nest("/guilds", guilds::router())
.nest("/invites", invites::router())
.nest("/me", me::router())
.layer(from_fn_with_state(app_state.clone(), CurrentUser::check_auth_layer));
.layer(from_fn_with_state(
app_state.clone(),
CurrentUser::check_auth_layer,
));
Router::new()
.route("/stats", get(stats::res))

View file

@ -2,13 +2,21 @@
use std::sync::Arc;
use axum::{
extract::{Query, State}, http::StatusCode, response::IntoResponse, routing::get, Extension, Json, Router
};
use ::uuid::Uuid;
use axum::{
Extension, Json, Router,
extract::{Query, State},
http::StatusCode,
response::IntoResponse,
routing::get,
};
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{StartAmountQuery, User}, utils::global_checks, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{StartAmountQuery, User},
utils::global_checks,
};
mod uuid;

View file

@ -3,12 +3,19 @@
use std::sync::Arc;
use axum::{
extract::{Path, State}, http::StatusCode, response::IntoResponse, Extension, Json
Extension, Json,
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use uuid::Uuid;
use crate::{
api::v1::auth::CurrentUser, error::Error, objects::{Me, User}, utils::global_checks, AppState
AppState,
api::v1::auth::CurrentUser,
error::Error,
objects::{Me, User},
utils::global_checks,
};
/// `GET /api/v1/users/{uuid}` Returns user with the given UUID

View file

@ -1,29 +1,32 @@
use argon2::Argon2;
use axum::{http::{header, Method}, Router};
use axum::{
Router,
http::{Method, header},
};
use clap::Parser;
use config::{Config, ConfigBuilder};
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
use diesel_async::pooled_connection::deadpool::Pool;
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
use error::Error;
use objects::MailClient;
use socketioxide::SocketIo;
use std::{sync::Arc, time::SystemTime};
use tower_http::cors::{AllowOrigin, CorsLayer};
use config::{Config, ConfigBuilder};
use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations};
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
type Conn =
deadpool::managed::Object<AsyncDieselConnectionManager<diesel_async::AsyncPgConnection>>;
mod config;
mod wordlist;
mod api;
mod config;
pub mod error;
pub mod objects;
pub mod schema;
pub mod utils;
mod socket;
pub mod utils;
mod wordlist;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
@ -129,9 +132,7 @@ async fn main() -> Result<(), Error> {
let cors = CorsLayer::new()
// Allow any origin (equivalent to allowed_origin_fn returning true)
.allow_origin(AllowOrigin::predicate(|_origin, _request_head| {
true
}))
.allow_origin(AllowOrigin::predicate(|_origin, _request_head| true))
.allow_methods(vec![
Method::GET,
Method::POST,
@ -157,14 +158,19 @@ async fn main() -> Result<(), Error> {
// Allow credentials
.allow_credentials(true);
let (socket_io, io) = SocketIo::builder().with_state(app_state.clone()).build_layer();
let (socket_io, io) = SocketIo::builder()
.with_state(app_state.clone())
.build_layer();
io.ns("/", socket::on_connect);
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.merge(api::router(web.backend_url.path().trim_end_matches("/"), app_state.clone()))
.merge(api::router(
web.backend_url.path().trim_end_matches("/"),
app_state.clone(),
))
.with_state(app_state)
.layer(cors)
.layer(socket_io);

View file

@ -2,24 +2,26 @@ use std::sync::Arc;
use log::info;
use rmpv::Value;
use socketioxide::{
extract::{AckSender, Data, SocketRef, State},
};
use socketioxide::extract::{AckSender, Data, SocketRef, State};
use crate::AppState;
pub async fn on_connect(State(app_state): State<Arc<AppState>>, socket: SocketRef, Data(data): Data<Value>) {
pub async fn on_connect(
State(_app_state): State<Arc<AppState>>,
socket: SocketRef,
Data(data): Data<Value>,
) {
socket.emit("auth", &data).ok();
socket.on("message", async |socket: SocketRef, Data::<Value>(data)| {
info!("{}", data);
info!("{data}");
socket.emit("message-back", &data).ok();
});
socket.on(
"message-with-ack",
async |Data::<Value>(data), ack: AckSender| {
info!("{}", data);
info!("{data}");
ack.send(&data).ok();
},
);

View file

@ -1,5 +1,5 @@
use rand::seq::IndexedRandom;
use std::sync::LazyLock;
use rand::{seq::IndexedRandom};
use axum::body::Bytes;
use axum_extra::extract::cookie::{Cookie, SameSite};
@ -20,7 +20,7 @@ use crate::{
error::Error,
objects::{HasIsAbove, HasUuid},
schema::users,
wordlist::{ADJECTIVES, ANIMALS}
wordlist::{ADJECTIVES, ANIMALS},
};
pub static EMAIL_REGEX: LazyLock<Regex> = LazyLock::new(|| {
@ -216,5 +216,5 @@ pub fn generate_device_name() -> String {
let adjective = ADJECTIVES.choose(&mut rng).unwrap();
let animal = ANIMALS.choose(&mut rng).unwrap();
return [*adjective, *animal].join(" ")
[*adjective, *animal].join(" ")
}

View file

@ -1,4 +1,4 @@
pub const ANIMALS: [&'static str; 223] = [
pub const ANIMALS: [&str; 223] = [
"Aardvark",
"Albatross",
"Alligator",
@ -224,7 +224,7 @@ pub const ANIMALS: [&'static str; 223] = [
"Zebra",
];
pub const ADJECTIVES: [&'static str; 765] = [
pub const ADJECTIVES: [&str; 765] = [
"Other",
"Such",
"First",
@ -990,4 +990,4 @@ pub const ADJECTIVES: [&'static str; 765] = [
"Vocal",
"Obscure",
"Innovative",
];
];