mirror of
https://github.com/n08i40k/schedule-parser-rusted.git
synced 2025-12-06 17:57:47 +03:00
Реформат путей к эндпоинтам.
Добавлен экстрактор пользователя с дополнительными полями.
Добавлена связь таблиц User и FCM.
Завершена реализация авторизации с помощью VK ID.
Добавлен эндпоинт fcm/update-callback/{version}.
This commit is contained in:
114
src/routes/vk_id/oauth.rs
Normal file
114
src/routes/vk_id/oauth.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
use self::schema::*;
|
||||
use crate::app_state::AppState;
|
||||
use crate::routes::schema::{IntoResponseAsError, ResponseError};
|
||||
use actix_web::{post, web};
|
||||
use serde::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Deserialize)]
|
||||
struct VkIdAuthResponse {
|
||||
refresh_token: String,
|
||||
access_token: String,
|
||||
id_token: String,
|
||||
token_type: String,
|
||||
expires_in: i32,
|
||||
user_id: i32,
|
||||
state: String,
|
||||
scope: String,
|
||||
}
|
||||
|
||||
#[utoipa::path(responses(
|
||||
(status = OK, body = Response),
|
||||
(
|
||||
status = NOT_ACCEPTABLE,
|
||||
body = ResponseError<ErrorCode>,
|
||||
example = json!({
|
||||
"code": "VK_ID_ERROR",
|
||||
"message": "VK server returned an error"
|
||||
})
|
||||
),
|
||||
))]
|
||||
#[post("/oauth")]
|
||||
async fn oauth(data: web::Json<Request>, app_state: web::Data<AppState>) -> ServiceResponse {
|
||||
let data = data.into_inner();
|
||||
let state = Uuid::new_v4().simple().to_string();
|
||||
|
||||
let vk_id = &app_state.vk_id;
|
||||
let client_id = vk_id.client_id.clone().to_string();
|
||||
|
||||
let mut params = HashMap::new();
|
||||
params.insert("grant_type", "authorization_code");
|
||||
params.insert("client_id", client_id.as_str());
|
||||
params.insert("state", state.as_str());
|
||||
params.insert("code_verifier", data.code_verifier.as_str());
|
||||
params.insert("code", data.code.as_str());
|
||||
params.insert("device_id", data.device_id.as_str());
|
||||
params.insert("redirect_uri", vk_id.redirect_url.as_str());
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
match client
|
||||
.post("https://id.vk.com/oauth2/auth")
|
||||
.form(¶ms)
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(res) => {
|
||||
if !res.status().is_success() {
|
||||
return ErrorCode::VkIdError.into_response();
|
||||
}
|
||||
|
||||
if let Ok(auth_data) = res.json::<VkIdAuthResponse>().await {
|
||||
Ok(Response {
|
||||
access_token: auth_data.id_token,
|
||||
})
|
||||
.into()
|
||||
} else {
|
||||
ErrorCode::VkIdError.into_response()
|
||||
}
|
||||
}
|
||||
Err(_) => ErrorCode::VkIdError.into_response(),
|
||||
}
|
||||
}
|
||||
|
||||
mod schema {
|
||||
use actix_macros::{IntoResponseErrorNamed, StatusCode};
|
||||
use derive_more::Display;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub type ServiceResponse = crate::routes::schema::Response<Response, ErrorCode>;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[schema(as = VkIdOAuth::Request)]
|
||||
pub struct Request {
|
||||
/// Код подтверждения authorization_code
|
||||
pub code: String,
|
||||
|
||||
/// Параметр для защиты передаваемых данных
|
||||
pub code_verifier: String,
|
||||
|
||||
/// Идентификатор устройства
|
||||
pub device_id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[schema(as = VkIdOAuth::Response)]
|
||||
pub struct Response {
|
||||
/// ID токен
|
||||
pub access_token: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, ToSchema, IntoResponseErrorNamed, StatusCode, Display)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
#[schema(as = VkIdOAuth::ErrorCode)]
|
||||
#[status_code = "actix_web::http::StatusCode::NOT_ACCEPTABLE"]
|
||||
pub enum ErrorCode {
|
||||
/// Сервер VK вернул ошибку
|
||||
#[display("VK server returned an error")]
|
||||
VkIdError,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user