mirror of
https://github.com/flibusta-apps/users_settings_server.git
synced 2026-03-03 15:10:51 +01:00
Add pre-commit config
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
use axum::{Router, response::IntoResponse, routing::{get, post}, extract::Path, Json, http::StatusCode};
|
||||
use axum::{
|
||||
extract::Path,
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
Json, Router,
|
||||
};
|
||||
use chrono::Duration;
|
||||
|
||||
use crate::prisma::chat_donate_notifications;
|
||||
|
||||
use super::Database;
|
||||
|
||||
|
||||
async fn is_need_send(
|
||||
Path(chat_id): Path<i64>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
async fn is_need_send(Path(chat_id): Path<i64>, db: Database) -> impl IntoResponse {
|
||||
const NOTIFICATION_DELTA_DAYS: i64 = 60;
|
||||
|
||||
let notification = db.chat_donate_notifications()
|
||||
let notification = db
|
||||
.chat_donate_notifications()
|
||||
.find_unique(chat_donate_notifications::chat_id::equals(chat_id))
|
||||
.exec()
|
||||
.await
|
||||
@@ -20,31 +23,24 @@ async fn is_need_send(
|
||||
|
||||
match notification {
|
||||
Some(notification) => {
|
||||
let result = notification.sended.naive_local() + Duration::days(NOTIFICATION_DELTA_DAYS) <= chrono::offset::Local::now().naive_local();
|
||||
let result = notification.sended.naive_local()
|
||||
+ Duration::days(NOTIFICATION_DELTA_DAYS)
|
||||
<= chrono::offset::Local::now().naive_local();
|
||||
Json(result).into_response()
|
||||
},
|
||||
}
|
||||
None => Json(true).into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn mark_sent(
|
||||
Path(chat_id): Path<i64>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
let _ = db.chat_donate_notifications()
|
||||
async fn mark_sent(Path(chat_id): Path<i64>, db: Database) -> impl IntoResponse {
|
||||
let _ = db
|
||||
.chat_donate_notifications()
|
||||
.upsert(
|
||||
chat_donate_notifications::chat_id::equals(chat_id),
|
||||
chat_donate_notifications::create(
|
||||
chat_id,
|
||||
chat_donate_notifications::create(chat_id, chrono::offset::Local::now().into(), vec![]),
|
||||
vec![chat_donate_notifications::sended::set(
|
||||
chrono::offset::Local::now().into(),
|
||||
vec![]
|
||||
),
|
||||
vec![
|
||||
chat_donate_notifications::sended::set(
|
||||
chrono::offset::Local::now().into()
|
||||
)
|
||||
]
|
||||
)],
|
||||
)
|
||||
.exec()
|
||||
.await;
|
||||
@@ -52,7 +48,6 @@ async fn mark_sent(
|
||||
StatusCode::OK
|
||||
}
|
||||
|
||||
|
||||
pub fn get_router() -> Router {
|
||||
Router::new()
|
||||
.route("/:chat_id/is_need_send", get(is_need_send))
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
use axum::{Router, response::IntoResponse, routing::get, Json, extract::Path, http::StatusCode};
|
||||
use axum::{extract::Path, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::prisma::language;
|
||||
use super::Database;
|
||||
|
||||
use crate::prisma::language;
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct LanguageDetail {
|
||||
@@ -12,24 +11,19 @@ pub struct LanguageDetail {
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
|
||||
impl From<language::Data> for LanguageDetail {
|
||||
fn from(value: language::Data) -> Self {
|
||||
let language::Data { id, label, code, .. } = value;
|
||||
let language::Data {
|
||||
id, label, code, ..
|
||||
} = value;
|
||||
|
||||
Self {
|
||||
id,
|
||||
label,
|
||||
code
|
||||
}
|
||||
Self { id, label, code }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async fn get_languages(
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
let languages: Vec<LanguageDetail> = db.language()
|
||||
async fn get_languages(db: Database) -> impl IntoResponse {
|
||||
let languages: Vec<LanguageDetail> = db
|
||||
.language()
|
||||
.find_many(vec![])
|
||||
.exec()
|
||||
.await
|
||||
@@ -41,12 +35,9 @@ async fn get_languages(
|
||||
Json(languages).into_response()
|
||||
}
|
||||
|
||||
|
||||
async fn get_language_by_code(
|
||||
Path(code): Path<String>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
let language = db.language()
|
||||
async fn get_language_by_code(Path(code): Path<String>, db: Database) -> impl IntoResponse {
|
||||
let language = db
|
||||
.language()
|
||||
.find_unique(language::code::equals(code))
|
||||
.exec()
|
||||
.await
|
||||
@@ -58,7 +49,6 @@ async fn get_language_by_code(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn get_router() -> Router {
|
||||
Router::new()
|
||||
.route("/", get(get_languages))
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
use axum::{Router, response::Response, http::{StatusCode, self, Request}, middleware::{Next, self}, Extension, routing::get};
|
||||
use axum::{
|
||||
http::{self, Request, StatusCode},
|
||||
middleware::{self, Next},
|
||||
response::Response,
|
||||
routing::get,
|
||||
Extension, Router,
|
||||
};
|
||||
use axum_prometheus::PrometheusMetricLayer;
|
||||
use tower_http::trace::{TraceLayer, self};
|
||||
use tracing::Level;
|
||||
use std::sync::Arc;
|
||||
use tower_http::trace::{self, TraceLayer};
|
||||
use tracing::Level;
|
||||
|
||||
use crate::{config::CONFIG, db::get_prisma_client, prisma::PrismaClient};
|
||||
|
||||
pub mod users;
|
||||
pub mod pagination;
|
||||
pub mod languages;
|
||||
pub mod donate_notifications;
|
||||
|
||||
pub mod languages;
|
||||
pub mod pagination;
|
||||
pub mod users;
|
||||
|
||||
pub type Database = Extension<Arc<PrismaClient>>;
|
||||
|
||||
|
||||
async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode> {
|
||||
let auth_header = req.headers()
|
||||
let auth_header = req
|
||||
.headers()
|
||||
.get(http::header::AUTHORIZATION)
|
||||
.and_then(|header| header.to_str().ok());
|
||||
|
||||
@@ -33,7 +38,6 @@ async fn auth<B>(req: Request<B>, next: Next<B>) -> Result<Response, StatusCode>
|
||||
Ok(next.run(req).await)
|
||||
}
|
||||
|
||||
|
||||
pub async fn get_router() -> Router {
|
||||
let client = Arc::new(get_prisma_client().await);
|
||||
|
||||
@@ -47,17 +51,15 @@ pub async fn get_router() -> Router {
|
||||
.layer(Extension(client))
|
||||
.layer(prometheus_layer);
|
||||
|
||||
let metric_router = Router::new()
|
||||
.route("/metrics", get(|| async move { metric_handle.render() }));
|
||||
let metric_router =
|
||||
Router::new().route("/metrics", get(|| async move { metric_handle.render() }));
|
||||
|
||||
Router::new()
|
||||
.nest("/", app_router)
|
||||
.nest("/", metric_router)
|
||||
.layer(
|
||||
TraceLayer::new_for_http()
|
||||
.make_span_with(trace::DefaultMakeSpan::new()
|
||||
.level(Level::INFO))
|
||||
.on_response(trace::DefaultOnResponse::new()
|
||||
.level(Level::INFO)),
|
||||
.make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO))
|
||||
.on_response(trace::DefaultOnResponse::new().level(Level::INFO)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct Pagination {
|
||||
#[serde(default = "default_page")]
|
||||
pub page: usize,
|
||||
#[serde(default = "default_size")]
|
||||
pub size: usize
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
fn default_page() -> usize { 1 }
|
||||
fn default_size() -> usize { 50 }
|
||||
fn default_page() -> usize {
|
||||
1
|
||||
}
|
||||
fn default_size() -> usize {
|
||||
50
|
||||
}
|
||||
|
||||
impl Pagination {
|
||||
pub fn skip(&self) -> i64 {
|
||||
@@ -22,28 +25,29 @@ impl Pagination {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct Page<T> where T: Serialize {
|
||||
pub struct Page<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
pub items: Vec<T>,
|
||||
pub total: usize,
|
||||
pub page: usize,
|
||||
pub size: usize,
|
||||
pub pages: usize
|
||||
pub pages: usize,
|
||||
}
|
||||
|
||||
impl<T> Page<T> where T: Serialize {
|
||||
pub fn create(
|
||||
items: Vec<T>,
|
||||
items_count: i64,
|
||||
pagination: Pagination
|
||||
) -> Self {
|
||||
impl<T> Page<T>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
pub fn create(items: Vec<T>, items_count: i64, pagination: Pagination) -> Self {
|
||||
Self {
|
||||
items,
|
||||
total: items_count.try_into().unwrap(),
|
||||
page: pagination.page,
|
||||
size: pagination.size,
|
||||
pages: (items_count as f64 / pagination.size as f64).ceil() as usize
|
||||
pages: (items_count as f64 / pagination.size as f64).ceil() as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
pub mod serializers;
|
||||
pub mod utils;
|
||||
|
||||
use axum::{Router, response::IntoResponse, routing::{get, post}, extract::{Query, Path}, Json, http::StatusCode};
|
||||
use crate::prisma::{user_settings, language_to_user, user_activity};
|
||||
use crate::prisma::{language_to_user, user_activity, user_settings};
|
||||
use axum::{
|
||||
extract::{Path, Query},
|
||||
http::StatusCode,
|
||||
response::IntoResponse,
|
||||
routing::{get, post},
|
||||
Json, Router,
|
||||
};
|
||||
|
||||
use self::{serializers::{UserDetail, CreateOrUpdateUserData}, utils::update_languages};
|
||||
use self::{
|
||||
serializers::{CreateOrUpdateUserData, UserDetail},
|
||||
utils::update_languages,
|
||||
};
|
||||
|
||||
use super::{pagination::{Pagination, Page}, Database};
|
||||
use super::{
|
||||
pagination::{Page, Pagination},
|
||||
Database,
|
||||
};
|
||||
|
||||
|
||||
async fn get_users(
|
||||
pagination: Query<Pagination>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
async fn get_users(pagination: Query<Pagination>, db: Database) -> impl IntoResponse {
|
||||
let pagination: Pagination = pagination.0;
|
||||
|
||||
let users_count = db.user_settings()
|
||||
.count(vec![])
|
||||
.exec()
|
||||
.await
|
||||
.unwrap();
|
||||
let users_count = db.user_settings().count(vec![]).exec().await.unwrap();
|
||||
|
||||
let users: Vec<UserDetail> = db.user_settings()
|
||||
let users: Vec<UserDetail> = db
|
||||
.user_settings()
|
||||
.find_many(vec![])
|
||||
.with(
|
||||
user_settings::languages::fetch(vec![])
|
||||
.with(
|
||||
language_to_user::language::fetch()
|
||||
)
|
||||
)
|
||||
.with(user_settings::languages::fetch(vec![]).with(language_to_user::language::fetch()))
|
||||
.order_by(user_settings::id::order(prisma_client_rust::Direction::Asc))
|
||||
.skip(pagination.skip())
|
||||
.take(pagination.take())
|
||||
@@ -39,26 +39,14 @@ async fn get_users(
|
||||
.map(|item| item.into())
|
||||
.collect();
|
||||
|
||||
Json(Page::create(
|
||||
users,
|
||||
users_count,
|
||||
pagination
|
||||
)).into_response()
|
||||
Json(Page::create(users, users_count, pagination)).into_response()
|
||||
}
|
||||
|
||||
|
||||
async fn get_user(
|
||||
Path(user_id): Path<i64>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
let user = db.user_settings()
|
||||
async fn get_user(Path(user_id): Path<i64>, db: Database) -> impl IntoResponse {
|
||||
let user = db
|
||||
.user_settings()
|
||||
.find_unique(user_settings::user_id::equals(user_id))
|
||||
.with(
|
||||
user_settings::languages::fetch(vec![])
|
||||
.with(
|
||||
language_to_user::language::fetch()
|
||||
)
|
||||
)
|
||||
.with(user_settings::languages::fetch(vec![]).with(language_to_user::language::fetch()))
|
||||
.exec()
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -70,12 +58,12 @@ async fn get_user(
|
||||
Json::<UserDetail>(user.unwrap().into()).into_response()
|
||||
}
|
||||
|
||||
|
||||
async fn create_or_update_user(
|
||||
db: Database,
|
||||
Json(data): Json<CreateOrUpdateUserData>,
|
||||
) -> impl IntoResponse {
|
||||
let user = db.user_settings()
|
||||
let user = db
|
||||
.user_settings()
|
||||
.upsert(
|
||||
user_settings::user_id::equals(data.user_id),
|
||||
user_settings::create(
|
||||
@@ -84,21 +72,16 @@ async fn create_or_update_user(
|
||||
data.first_name.clone(),
|
||||
data.username.clone(),
|
||||
data.source.clone(),
|
||||
vec![]
|
||||
vec![],
|
||||
),
|
||||
vec![
|
||||
user_settings::last_name::set(data.last_name),
|
||||
user_settings::first_name::set(data.first_name),
|
||||
user_settings::username::set(data.username),
|
||||
user_settings::source::set(data.source)
|
||||
]
|
||||
)
|
||||
.with(
|
||||
user_settings::languages::fetch(vec![])
|
||||
.with(
|
||||
language_to_user::language::fetch()
|
||||
)
|
||||
user_settings::source::set(data.source),
|
||||
],
|
||||
)
|
||||
.with(user_settings::languages::fetch(vec![]).with(language_to_user::language::fetch()))
|
||||
.exec()
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -106,14 +89,10 @@ async fn create_or_update_user(
|
||||
let user_id = user.id;
|
||||
update_languages(user, data.allowed_langs, db.clone()).await;
|
||||
|
||||
let user = db.user_settings()
|
||||
let user = db
|
||||
.user_settings()
|
||||
.find_unique(user_settings::id::equals(user_id))
|
||||
.with(
|
||||
user_settings::languages::fetch(vec![])
|
||||
.with(
|
||||
language_to_user::language::fetch()
|
||||
)
|
||||
)
|
||||
.with(user_settings::languages::fetch(vec![]).with(language_to_user::language::fetch()))
|
||||
.exec()
|
||||
.await
|
||||
.unwrap()
|
||||
@@ -122,12 +101,9 @@ async fn create_or_update_user(
|
||||
Json::<UserDetail>(user.into()).into_response()
|
||||
}
|
||||
|
||||
|
||||
async fn update_activity(
|
||||
Path(user_id): Path<i64>,
|
||||
db: Database
|
||||
) -> impl IntoResponse {
|
||||
let user = db.user_settings()
|
||||
async fn update_activity(Path(user_id): Path<i64>, db: Database) -> impl IntoResponse {
|
||||
let user = db
|
||||
.user_settings()
|
||||
.find_unique(user_settings::user_id::equals(user_id))
|
||||
.exec()
|
||||
.await
|
||||
@@ -138,17 +114,18 @@ async fn update_activity(
|
||||
None => return StatusCode::NOT_FOUND.into_response(),
|
||||
};
|
||||
|
||||
let _ = db.user_activity()
|
||||
let _ = db
|
||||
.user_activity()
|
||||
.upsert(
|
||||
user_activity::user_id::equals(user.id),
|
||||
user_activity::create(
|
||||
chrono::offset::Local::now().into(),
|
||||
user_settings::id::equals(user.id),
|
||||
vec![]
|
||||
vec![],
|
||||
),
|
||||
vec![
|
||||
user_activity::updated::set(chrono::offset::Local::now().into())
|
||||
]
|
||||
vec![user_activity::updated::set(
|
||||
chrono::offset::Local::now().into(),
|
||||
)],
|
||||
)
|
||||
.exec()
|
||||
.await;
|
||||
@@ -156,7 +133,6 @@ async fn update_activity(
|
||||
StatusCode::OK.into_response()
|
||||
}
|
||||
|
||||
|
||||
pub fn get_router() -> Router {
|
||||
Router::new()
|
||||
.route("/", get(get_users))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use crate::prisma::{user_settings, language};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::prisma::{language, user_settings};
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct UserLanguage {
|
||||
@@ -10,18 +9,16 @@ pub struct UserLanguage {
|
||||
pub code: String,
|
||||
}
|
||||
|
||||
|
||||
impl From<language::Data> for UserLanguage {
|
||||
fn from(value: language::Data) -> Self {
|
||||
Self {
|
||||
id: value.id,
|
||||
label: value.label,
|
||||
code: value.code
|
||||
code: value.code,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct UserDetail {
|
||||
pub id: i32,
|
||||
@@ -30,14 +27,14 @@ pub struct UserDetail {
|
||||
pub first_name: String,
|
||||
pub username: String,
|
||||
pub source: String,
|
||||
pub allowed_langs: Vec<UserLanguage>
|
||||
pub allowed_langs: Vec<UserLanguage>,
|
||||
}
|
||||
|
||||
|
||||
impl From<user_settings::Data> for UserDetail {
|
||||
fn from(value: user_settings::Data) -> Self {
|
||||
let allowed_langs: Vec<UserLanguage> = value
|
||||
.languages.unwrap()
|
||||
.languages
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|item| *item.language.unwrap())
|
||||
.map(|item| item.into())
|
||||
@@ -50,7 +47,7 @@ impl From<user_settings::Data> for UserDetail {
|
||||
first_name: value.first_name,
|
||||
username: value.username,
|
||||
source: value.source,
|
||||
allowed_langs
|
||||
allowed_langs,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,5 +59,5 @@ pub struct CreateOrUpdateUserData {
|
||||
pub first_name: String,
|
||||
pub username: String,
|
||||
pub source: String,
|
||||
pub allowed_langs: Vec<String>
|
||||
pub allowed_langs: Vec<String>,
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::{prisma::{user_settings, language, language_to_user}, views::Database};
|
||||
use crate::{
|
||||
prisma::{language, language_to_user, user_settings},
|
||||
views::Database,
|
||||
};
|
||||
|
||||
|
||||
pub async fn update_languages(
|
||||
user: user_settings::Data,
|
||||
new_langs: Vec<String>,
|
||||
db: Database
|
||||
) {
|
||||
pub async fn update_languages(user: user_settings::Data, new_langs: Vec<String>, db: Database) {
|
||||
// Delete
|
||||
{
|
||||
let need_delete: Vec<_> = user.languages().unwrap()
|
||||
let need_delete: Vec<_> = user
|
||||
.languages()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|item| {
|
||||
let language::Data{ id, code, .. } = *item.clone().language.unwrap();
|
||||
let language::Data { id, code, .. } = *item.clone().language.unwrap();
|
||||
(id, code)
|
||||
})
|
||||
.filter(|(_, code)| !new_langs.contains(code))
|
||||
.map(|(id, _)| id)
|
||||
.collect();
|
||||
|
||||
let _ = db.language_to_user()
|
||||
.delete_many(
|
||||
vec![language_to_user::id::in_vec(need_delete)]
|
||||
)
|
||||
let _ = db
|
||||
.language_to_user()
|
||||
.delete_many(vec![language_to_user::id::in_vec(need_delete)])
|
||||
.exec()
|
||||
.await;
|
||||
}
|
||||
|
||||
// Create
|
||||
{
|
||||
let languages: HashMap<_, _> = db.language()
|
||||
let languages: HashMap<_, _> = db
|
||||
.language()
|
||||
.find_many(vec![])
|
||||
.exec()
|
||||
.await
|
||||
@@ -39,7 +39,9 @@ pub async fn update_languages(
|
||||
.map(|l| (l.code, l.id))
|
||||
.collect();
|
||||
|
||||
let current_langs: Vec<_> = user.languages().unwrap()
|
||||
let current_langs: Vec<_> = user
|
||||
.languages()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|item| item.clone().language.unwrap().code)
|
||||
.collect();
|
||||
@@ -50,18 +52,17 @@ pub async fn update_languages(
|
||||
.map(|code| *languages.get(&code).unwrap())
|
||||
.collect();
|
||||
|
||||
let _ = db.language_to_user()
|
||||
.create_many(
|
||||
need_create
|
||||
.iter()
|
||||
.map(|language_id| language_to_user::create_unchecked(
|
||||
*language_id,
|
||||
user.id,
|
||||
vec![]
|
||||
))
|
||||
.collect()
|
||||
)
|
||||
.exec()
|
||||
.await;
|
||||
let _ = db
|
||||
.language_to_user()
|
||||
.create_many(
|
||||
need_create
|
||||
.iter()
|
||||
.map(|language_id| {
|
||||
language_to_user::create_unchecked(*language_id, user.id, vec![])
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.exec()
|
||||
.await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user