mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 09:47:50 +03:00
refactor(android)!: remove FCM support
This commit is contained in:
716
Cargo.lock
generated
716
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -29,9 +29,6 @@ diesel-derive-enum = { git = "https://github.com/Havunen/diesel-derive-enum.git"
|
|||||||
# logging
|
# logging
|
||||||
env_logger = "0.11.7"
|
env_logger = "0.11.7"
|
||||||
|
|
||||||
# TODO: remove support for android app and fcm?
|
|
||||||
firebase-messaging-rs = { git = "https://github.com/i10416/firebase-messaging-rs.git" }
|
|
||||||
|
|
||||||
# async
|
# async
|
||||||
tokio = { version = "1.44.1", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.44.1", features = ["macros", "rt-multi-thread"] }
|
||||||
tokio-util = "0.7.16"
|
tokio-util = "0.7.16"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ pub mod users {
|
|||||||
use crate::database::schema::users::dsl::*;
|
use crate::database::schema::users::dsl::*;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use diesel::{ExpressionMethods, QueryResult, insert_into};
|
use diesel::{insert_into, ExpressionMethods, QueryResult};
|
||||||
use diesel::{QueryDsl, RunQueryDsl};
|
use diesel::{QueryDsl, RunQueryDsl};
|
||||||
use diesel::{SaveChangesDsl, SelectableHelper};
|
use diesel::{SaveChangesDsl, SelectableHelper};
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
@@ -146,19 +146,3 @@ pub mod users {
|
|||||||
.execute(state.get_database().await.deref_mut())
|
.execute(state.get_database().await.deref_mut())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod fcm {
|
|
||||||
use crate::database::models::{FCM, User};
|
|
||||||
use crate::state::AppState;
|
|
||||||
use actix_web::web;
|
|
||||||
use diesel::QueryDsl;
|
|
||||||
use diesel::RunQueryDsl;
|
|
||||||
use diesel::{BelongingToDsl, QueryResult, SelectableHelper};
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
|
|
||||||
pub async fn from_user(state: &web::Data<AppState>, user: &User) -> QueryResult<FCM> {
|
|
||||||
FCM::belonging_to(&user)
|
|
||||||
.select(FCM::as_select())
|
|
||||||
.get_result(state.get_database().await.deref_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
use crate::database::driver;
|
use crate::database::driver;
|
||||||
use crate::database::models::{User, FCM};
|
use crate::database::models::User;
|
||||||
use crate::extractors::base::{AsyncExtractor, FromRequestAsync};
|
use crate::extractors::base::FromRequestAsync;
|
||||||
use crate::state::AppState;
|
use crate::state::AppState;
|
||||||
use crate::utility::jwt;
|
use crate::utility::jwt;
|
||||||
use actix_macros::MiddlewareError;
|
use actix_macros::MiddlewareError;
|
||||||
use actix_web::body::BoxBody;
|
use actix_web::body::BoxBody;
|
||||||
use actix_web::dev::Payload;
|
use actix_web::dev::Payload;
|
||||||
use actix_web::http::header;
|
use actix_web::http::header;
|
||||||
use actix_web::{web, FromRequest, HttpRequest};
|
use actix_web::{web, HttpRequest};
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@@ -95,48 +95,3 @@ impl FromRequestAsync for User {
|
|||||||
.map_err(|_| Error::NoUser.into())
|
.map_err(|_| Error::NoUser.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UserExtractor<const FCM: bool> {
|
|
||||||
user: User,
|
|
||||||
|
|
||||||
fcm: Option<FCM>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const FCM: bool> UserExtractor<{ FCM }> {
|
|
||||||
pub fn user(&self) -> &User {
|
|
||||||
&self.user
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn fcm(&self) -> &Option<FCM> {
|
|
||||||
if !FCM {
|
|
||||||
panic!("FCM marked as not required, but it has been requested")
|
|
||||||
}
|
|
||||||
|
|
||||||
&self.fcm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extractor of user and additional parameters from request with Bearer token.
|
|
||||||
impl<const FCM: bool> FromRequestAsync for UserExtractor<{ FCM }> {
|
|
||||||
type Error = actix_web::Error;
|
|
||||||
|
|
||||||
async fn from_request_async(
|
|
||||||
req: &HttpRequest,
|
|
||||||
payload: &mut Payload,
|
|
||||||
) -> Result<Self, Self::Error> {
|
|
||||||
let user = AsyncExtractor::<User>::from_request(req, payload)
|
|
||||||
.await?
|
|
||||||
.into_inner();
|
|
||||||
|
|
||||||
let app_state = req.app_data::<web::Data<AppState>>().unwrap();
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
fcm: if FCM {
|
|
||||||
driver::fcm::from_user(&app_state, &user).await.ok()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
user,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@@ -1,13 +1,13 @@
|
|||||||
use crate::middlewares::authorization::JWTAuthorization;
|
use crate::middlewares::authorization::JWTAuthorization;
|
||||||
use crate::middlewares::content_type::ContentTypeBootstrap;
|
use crate::middlewares::content_type::ContentTypeBootstrap;
|
||||||
use crate::state::{AppState, new_app_state};
|
use crate::state::{new_app_state, AppState};
|
||||||
use actix_web::dev::{ServiceFactory, ServiceRequest};
|
use actix_web::dev::{ServiceFactory, ServiceRequest};
|
||||||
use actix_web::{App, Error, HttpServer};
|
use actix_web::{App, Error, HttpServer};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use log::info;
|
use log::info;
|
||||||
use std::io;
|
use std::io;
|
||||||
use utoipa_actix_web::AppExt;
|
|
||||||
use utoipa_actix_web::scope::Scope;
|
use utoipa_actix_web::scope::Scope;
|
||||||
|
use utoipa_actix_web::AppExt;
|
||||||
use utoipa_rapidoc::RapiDoc;
|
use utoipa_rapidoc::RapiDoc;
|
||||||
|
|
||||||
mod state;
|
mod state;
|
||||||
@@ -51,11 +51,6 @@ pub fn get_api_scope<
|
|||||||
.service(routes::schedule::teacher)
|
.service(routes::schedule::teacher)
|
||||||
.service(routes::schedule::teacher_names);
|
.service(routes::schedule::teacher_names);
|
||||||
|
|
||||||
let fcm_scope = utoipa_actix_web::scope("/fcm")
|
|
||||||
.wrap(JWTAuthorization::default())
|
|
||||||
.service(routes::fcm::update_callback)
|
|
||||||
.service(routes::fcm::set_token);
|
|
||||||
|
|
||||||
let flow_scope = utoipa_actix_web::scope("/flow")
|
let flow_scope = utoipa_actix_web::scope("/flow")
|
||||||
.wrap(JWTAuthorization {
|
.wrap(JWTAuthorization {
|
||||||
ignore: &["/telegram-auth"],
|
ignore: &["/telegram-auth"],
|
||||||
@@ -70,7 +65,6 @@ pub fn get_api_scope<
|
|||||||
.service(auth_scope)
|
.service(auth_scope)
|
||||||
.service(users_scope)
|
.service(users_scope)
|
||||||
.service(schedule_scope)
|
.service(schedule_scope)
|
||||||
.service(fcm_scope)
|
|
||||||
.service(flow_scope)
|
.service(flow_scope)
|
||||||
.service(vk_id_scope)
|
.service(vk_id_scope)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
mod set_token;
|
|
||||||
mod update_callback;
|
|
||||||
|
|
||||||
pub use set_token::*;
|
|
||||||
pub use update_callback::*;
|
|
||||||
@@ -1,94 +0,0 @@
|
|||||||
use crate::database;
|
|
||||||
use crate::database::models::FCM;
|
|
||||||
use crate::extractors::authorized_user::UserExtractor;
|
|
||||||
use crate::extractors::base::AsyncExtractor;
|
|
||||||
use crate::state::AppState;
|
|
||||||
use actix_web::{HttpResponse, Responder, patch, web};
|
|
||||||
use diesel::{RunQueryDsl, SaveChangesDsl};
|
|
||||||
use firebase_messaging_rs::topic::TopicManagementSupport;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use std::ops::DerefMut;
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
struct Params {
|
|
||||||
pub token: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_fcm(
|
|
||||||
app_state: &web::Data<AppState>,
|
|
||||||
user_data: &UserExtractor<true>,
|
|
||||||
token: String,
|
|
||||||
) -> Result<FCM, diesel::result::Error> {
|
|
||||||
match user_data.fcm() {
|
|
||||||
Some(fcm) => {
|
|
||||||
let mut fcm = fcm.clone();
|
|
||||||
fcm.token = token;
|
|
||||||
|
|
||||||
Ok(fcm)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
let fcm = FCM {
|
|
||||||
user_id: user_data.user().id.clone(),
|
|
||||||
token,
|
|
||||||
topics: vec![],
|
|
||||||
};
|
|
||||||
|
|
||||||
match diesel::insert_into(database::schema::fcm::table)
|
|
||||||
.values(&fcm)
|
|
||||||
.execute(app_state.get_database().await.deref_mut())
|
|
||||||
{
|
|
||||||
Ok(_) => Ok(fcm),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[utoipa::path(responses((status = OK)))]
|
|
||||||
#[patch("/set-token")]
|
|
||||||
pub async fn set_token(
|
|
||||||
app_state: web::Data<AppState>,
|
|
||||||
web::Query(params): web::Query<Params>,
|
|
||||||
user_data: AsyncExtractor<UserExtractor<true>>,
|
|
||||||
) -> impl Responder {
|
|
||||||
let user_data = user_data.into_inner();
|
|
||||||
|
|
||||||
// If token not changes - exit.
|
|
||||||
if let Some(fcm) = user_data.fcm() {
|
|
||||||
if fcm.token == params.token {
|
|
||||||
return HttpResponse::Ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let fcm = get_fcm(&app_state, &user_data, params.token.clone()).await;
|
|
||||||
if let Err(e) = fcm {
|
|
||||||
eprintln!("Failed to get FCM: {e}");
|
|
||||||
return HttpResponse::Ok();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut fcm = fcm.ok().unwrap();
|
|
||||||
|
|
||||||
// Add default topics.
|
|
||||||
if !fcm.topics.contains(&Some("common".to_string())) {
|
|
||||||
fcm.topics.push(Some("common".to_string()));
|
|
||||||
}
|
|
||||||
|
|
||||||
fcm.save_changes::<FCM>(app_state.get_database().await.deref_mut())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let fcm_client = app_state.get_fcm_client().await.unwrap();
|
|
||||||
|
|
||||||
for topic in fcm.topics.clone() {
|
|
||||||
if let Some(topic) = topic {
|
|
||||||
if let Err(error) = fcm_client
|
|
||||||
.register_token_to_topic(&*topic, &*fcm.token)
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
eprintln!("Failed to subscribe token to topic: {:?}", error);
|
|
||||||
return HttpResponse::Ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HttpResponse::Ok()
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
use crate::database::driver::users::UserSave;
|
|
||||||
use crate::database::models::User;
|
|
||||||
use crate::extractors::base::AsyncExtractor;
|
|
||||||
use crate::state::AppState;
|
|
||||||
use actix_web::{HttpResponse, Responder, post, web};
|
|
||||||
|
|
||||||
#[utoipa::path(responses(
|
|
||||||
(status = OK),
|
|
||||||
(status = INTERNAL_SERVER_ERROR)
|
|
||||||
))]
|
|
||||||
#[post("/update-callback/{version}")]
|
|
||||||
async fn update_callback(
|
|
||||||
app_state: web::Data<AppState>,
|
|
||||||
version: web::Path<String>,
|
|
||||||
user: AsyncExtractor<User>,
|
|
||||||
) -> impl Responder {
|
|
||||||
let mut user = user.into_inner();
|
|
||||||
|
|
||||||
user.android_version = Some(version.into_inner());
|
|
||||||
|
|
||||||
user.save(&app_state).await.unwrap();
|
|
||||||
|
|
||||||
HttpResponse::Ok()
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod fcm;
|
|
||||||
pub mod flow;
|
pub mod flow;
|
||||||
pub mod schedule;
|
pub mod schedule;
|
||||||
mod schema;
|
mod schema;
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ pub mod user {
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
//noinspection SpellCheckingInspection
|
//noinspection SpellCheckingInspection
|
||||||
/// Используется для скрытия чувствительных полей, таких как хеш пароля или FCM
|
/// Используется для скрытия чувствительных полей, таких как хеш пароля
|
||||||
#[derive(Serialize, utoipa::ToSchema, ResponderJson, OkResponse)]
|
#[derive(Serialize, utoipa::ToSchema, ResponderJson, OkResponse)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct UserResponse {
|
pub struct UserResponse {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
use firebase_messaging_rs::FCMClient;
|
|
||||||
use std::env;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct FCMClientData;
|
|
||||||
|
|
||||||
impl FCMClientData {
|
|
||||||
pub async fn new() -> Option<Mutex<FCMClient>> {
|
|
||||||
match env::var("GOOGLE_APPLICATION_CREDENTIALS") {
|
|
||||||
Ok(_) => Some(Mutex::new(FCMClient::new().await.unwrap())),
|
|
||||||
Err(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,8 @@
|
|||||||
mod env;
|
mod env;
|
||||||
mod fcm_client;
|
|
||||||
|
|
||||||
pub use crate::state::env::AppEnv;
|
pub use crate::state::env::AppEnv;
|
||||||
use crate::state::fcm_client::FCMClientData;
|
|
||||||
use actix_web::web;
|
use actix_web::web;
|
||||||
use diesel::{Connection, PgConnection};
|
use diesel::{Connection, PgConnection};
|
||||||
use firebase_messaging_rs::FCMClient;
|
|
||||||
use providers::base::{ScheduleProvider, ScheduleSnapshot};
|
use providers::base::{ScheduleProvider, ScheduleSnapshot};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -18,7 +15,6 @@ pub struct AppState {
|
|||||||
database: Mutex<PgConnection>,
|
database: Mutex<PgConnection>,
|
||||||
providers: HashMap<String, Arc<dyn ScheduleProvider>>,
|
providers: HashMap<String, Arc<dyn ScheduleProvider>>,
|
||||||
env: AppEnv,
|
env: AppEnv,
|
||||||
fcm_client: Option<Mutex<FCMClient>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState {
|
impl AppState {
|
||||||
@@ -62,7 +58,6 @@ impl AppState {
|
|||||||
),
|
),
|
||||||
env,
|
env,
|
||||||
providers,
|
providers,
|
||||||
fcm_client: FCMClientData::new().await,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if this.env.schedule.auto_update {
|
if this.env.schedule.auto_update {
|
||||||
@@ -92,13 +87,6 @@ impl AppState {
|
|||||||
pub fn get_env(&self) -> &AppEnv {
|
pub fn get_env(&self) -> &AppEnv {
|
||||||
&self.env
|
&self.env
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_fcm_client(&'_ self) -> Option<MutexGuard<'_, FCMClient>> {
|
|
||||||
match &self.fcm_client {
|
|
||||||
Some(client) => Some(client.lock().await),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new object web::Data<AppState>.
|
/// Create a new object web::Data<AppState>.
|
||||||
|
|||||||
Reference in New Issue
Block a user