fix: insert new token, serve a default skin, log

This commit is contained in:
dev@ftbsc 2023-01-22 19:03:03 +01:00
parent 0b19c94acf
commit 87e87811b3
3 changed files with 54 additions and 50 deletions

View file

@ -10,7 +10,7 @@ pub struct Error {
pub cause: String, pub cause: String,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct Agent { pub struct Agent {
pub name: String, pub name: String,
pub version: u32, pub version: u32,
@ -23,7 +23,17 @@ pub struct Property {
pub signature: Option<String>, pub signature: Option<String>,
} }
#[derive(Serialize, Deserialize)] impl Property {
pub fn default_skin() -> Property {
Property {
name: "textures".into(),
value: "ewogICJ0aW1lc3RhbXAiIDogMTY3NDQwNDEzNjYyMiwKICAicHJvZmlsZUlkIiA6ICJjYjIzZWZhOWY1N2U0ZTQyOGE0MDU2OTM4NDlhODAxZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJWMUdHTyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9jNzgzMWE4MjAwN2FkNDNjY2ZkMGYyNThiMmJjNDQyYmI1MmE2ZTYxOWJlYzZmZjg5NDRkZWFkOWFhYTQ3MjVjIgogICAgfQogIH0KfQ==".into(),
signature: Some("pnWuF/KetMbydKaBAEXmoI2evgjvafa0CBJhNnph5JE7SN2JXZjdgy/SHLZLBMZoWBW7JRgpz0pFPhXOtPA5NtJYSKWQPXP04DY+x8Am3K3H1LqW92M8EPR5kJl+5KvlARASiqjnlobDoDIMvdG1748bVDUHY5GdlCZFaUQHmGiq9IWSnG65Ejgc/O1SkP/x6MaQrqW8XgNyR/f4oTOoYeSYThxsfqGmEgFl8SmcDYiUDwRXdJThsRRQMS98GMMWlQ0ujLjg6MGLdLwoNf4R3hU1vIB3o6BhXt+GydKHhy0xMtmqmYeS7YB6gAlhKG+YAVJisFIfwNGPLUt1qlIi8aMav+pw0yBqmzD8Uq8cqJrYdokB7kBE0t+6iHUX6nSXt0zUZSE+sQ4Hd5AQEV7rwcYTVYdmCA8RtlZZKK0zXQXTiuRpaDHDe9UYe5CNEmDnq1Plbz7w7JNMnNEVhOlCRJXRzrc6FHLWZT46QOC+Vhqz3/rpi7qEopgBLusQSJIox2lh6Ccc1tP/AZbFQjdPcks6+gpFOBYqF/+zcCJD/1UkXe3diIkgX9SqHIKPM0OtpsHO5Z4+SjtNIKUGUi7qjfe4NFSg+bUX2unsha9oHEaGir93cCIBO+liDlk5ZNc60wtncuoTnLtmKvlXHTZiBMGMRflIXkHQX5n8HYmC0LE=".into()),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct User { pub struct User {
pub id: Uuid, pub id: Uuid,
pub username: String, pub username: String,
@ -38,23 +48,23 @@ pub struct SessionUser {
pub properties: Option<Vec<Property>>, pub properties: Option<Vec<Property>>,
} }
#[derive(Serialize, Deserialize, Clone)] #[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Profile { pub struct Profile {
pub name: String, pub name: String,
pub id: Uuid, pub id: Uuid,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct AuthenticateRequest { pub struct AuthenticateRequest {
pub agent: Agent, pub agent: Agent,
pub username: String, pub username: String,
pub password: String, pub password: String,
pub clientToken: Option<Uuid>, pub clientToken: Option<String>,
pub requestUser: Option<bool>, pub requestUser: Option<bool>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct AuthenticateResponse { pub struct AuthenticateResponse {
pub user: User, pub user: User,
pub clientToken: String, pub clientToken: String,
@ -63,7 +73,7 @@ pub struct AuthenticateResponse {
pub selectedProfile: Profile, pub selectedProfile: Profile,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct RefreshRequest { pub struct RefreshRequest {
pub accessToken: String, pub accessToken: String,
pub clientToken: String, pub clientToken: String,
@ -71,7 +81,7 @@ pub struct RefreshRequest {
pub requestUser: Option<bool>, pub requestUser: Option<bool>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct RefreshResponse { pub struct RefreshResponse {
pub accessToken: String, pub accessToken: String,
pub clientToken: String, pub clientToken: String,
@ -79,7 +89,7 @@ pub struct RefreshResponse {
pub user: Option<User>, pub user: Option<User>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct ValidateRequest { pub struct ValidateRequest {
pub accessToken: String, pub accessToken: String,
pub clientToken: Option<String>, pub clientToken: Option<String>,
@ -93,7 +103,7 @@ pub struct SignoutRequest {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Debug)]
pub struct JoinRequest { pub struct JoinRequest {
pub accessToken: String, pub accessToken: String,
pub selectedProfile: Uuid, pub selectedProfile: Uuid,

View file

@ -2,11 +2,13 @@ use axum::{extract::State, Json, http::StatusCode};
use chrono::Utc; use chrono::Utc;
use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, ActiveValue::NotSet, Set}; use sea_orm::{EntityTrait, QueryFilter, ColumnTrait, ActiveValue::NotSet, Set};
use uuid::Uuid; use uuid::Uuid;
use tracing::{info, warn};
use crate::{entities, AppState, proto}; use crate::{entities, AppState, proto};
pub async fn validate(State(state): State<AppState>, Json(payload): Json<proto::ValidateRequest>) -> StatusCode { pub async fn validate(State(state): State<AppState>, Json(payload): Json<proto::ValidateRequest>) -> StatusCode {
info!(target: "AUTH", "[VALIDATE] called with {:?}", payload);
let token = entities::token::Entity::find().filter( let token = entities::token::Entity::find().filter(
entities::token::Column::AccessToken.eq(payload.accessToken) entities::token::Column::AccessToken.eq(payload.accessToken)
).one(&state.db).await.unwrap(); ).one(&state.db).await.unwrap();
@ -14,11 +16,13 @@ pub async fn validate(State(state): State<AppState>, Json(payload): Json<proto::
if let Some(_t) = token { if let Some(_t) = token {
StatusCode::NO_CONTENT StatusCode::NO_CONTENT
} else { } else {
warn!(target: "AUTH", "[VALIDATE] invalid token!");
StatusCode::UNAUTHORIZED StatusCode::UNAUTHORIZED
} }
} }
pub async fn refresh(State(state): State<AppState>, Json(payload): Json<proto::RefreshRequest>) -> Result<Json<proto::RefreshResponse>, StatusCode> { pub async fn refresh(State(state): State<AppState>, Json(payload): Json<proto::RefreshRequest>) -> Result<Json<proto::RefreshResponse>, StatusCode> {
info!(target: "AUTH", "[REFRESH] called with {:?}", payload);
let token = entities::token::Entity::find().filter( let token = entities::token::Entity::find().filter(
entities::token::Column::AccessToken.eq(payload.accessToken.clone()) entities::token::Column::AccessToken.eq(payload.accessToken.clone())
).one(&state.db).await.unwrap(); ).one(&state.db).await.unwrap();
@ -26,37 +30,31 @@ pub async fn refresh(State(state): State<AppState>, Json(payload): Json<proto::R
if let Some(t) = token { if let Some(t) = token {
// TODO if user requests profile, fetch it and include it // TODO if user requests profile, fetch it and include it
let user = entities::user::Entity::find_by_id(t.user_id).one(&state.db).await.unwrap().unwrap(); let user = entities::user::Entity::find_by_id(t.user_id).one(&state.db).await.unwrap().unwrap();
entities::token::Entity::delete( entities::token::Entity::delete_by_id(t.id).exec(&state.db).await.unwrap();
entities::token::ActiveModel{
id: NotSet,
access_token: Set(payload.accessToken.clone()),
created_at: NotSet,
user_id: NotSet,
}
).exec(&state.db).await.unwrap();
let new_access_token = Uuid::new_v4(); // TODO same as with authenticate let new_access_token = Uuid::new_v4(); // TODO same as with authenticate
entities::token::Entity::insert( entities::token::Entity::insert(
entities::token::ActiveModel{ entities::token::ActiveModel{
id: NotSet, id: NotSet,
access_token: Set(payload.accessToken.clone()), access_token: Set(new_access_token.to_string()),
created_at: Set(Utc::now()), created_at: Set(Utc::now()),
user_id: Set(user.id), user_id: Set(t.user_id),
} }
).exec(&state.db).await.unwrap(); ).exec(&state.db).await.unwrap();
Ok(Json( let response = proto::RefreshResponse {
proto::RefreshResponse { accessToken: new_access_token.to_string(),
accessToken: new_access_token.to_string(), clientToken: payload.clientToken,
clientToken: "idc".into(), selectedProfile: proto::Profile { id: user.uuid, name: user.name },
selectedProfile: proto::Profile { id: user.uuid, name: user.name }, user: None,
user: None, };
} info!(target: "AUTH", "[REFRESH] answering with {:?}", response);
)) Ok(Json(response))
} else { } else {
Err(StatusCode::UNAUTHORIZED) Err(StatusCode::UNAUTHORIZED)
} }
} }
pub async fn authenticate(State(state): State<AppState>, Json(payload): Json<proto::AuthenticateRequest>) -> Result<Json<proto::AuthenticateResponse>, StatusCode> { pub async fn authenticate(State(state): State<AppState>, Json(payload): Json<proto::AuthenticateRequest>) -> Result<Json<proto::AuthenticateResponse>, StatusCode> {
info!(target: "AUTH", "[AUTHENTICATE] called with {:?}", payload);
let user = entities::user::Entity::find().filter( let user = entities::user::Entity::find().filter(
entities::user::Column::Name.eq(payload.username) entities::user::Column::Name.eq(payload.username)
).one(&state.db).await.unwrap(); ).one(&state.db).await.unwrap();
@ -71,20 +69,20 @@ pub async fn authenticate(State(state): State<AppState>, Json(payload): Json<pro
access_token: Set(access_token.clone()), access_token: Set(access_token.clone()),
created_at: Set(Utc::now()), created_at: Set(Utc::now()),
}).exec(&state.db).await.unwrap(); }).exec(&state.db).await.unwrap();
let client_token = payload.clientToken.unwrap_or(Uuid::new_v4()); let client_token = payload.clientToken.unwrap_or(Uuid::new_v4().to_string());
let profile = proto::Profile { let profile = proto::Profile {
name: u.name.clone(), name: u.name.clone(),
id: u.uuid, id: u.uuid,
}; };
Ok(Json( let response =proto::AuthenticateResponse {
proto::AuthenticateResponse { accessToken: access_token,
accessToken: access_token, user: proto::User { id: u.uuid, username: u.name, properties: Some(vec![ proto::Property::default_skin() ]) },
user: proto::User { id: u.uuid, username: u.name, properties: Some(vec![]) }, clientToken: client_token,
clientToken: client_token.to_string(), availableProfiles: vec![profile.clone()],
availableProfiles: vec![profile.clone()], selectedProfile: profile,
selectedProfile: profile, };
} info!(target: "AUTH", "[AUTHENTICATE] answering with {:?}", response);
)) Ok(Json(response))
} else { } else {
Err(StatusCode::UNAUTHORIZED) Err(StatusCode::UNAUTHORIZED)
} }

View file

@ -10,6 +10,7 @@ use crate::{AppState, proto, JoinAttempt, entities};
pub async fn join(State(state): State<AppState>, Json(payload): Json<proto::JoinRequest>) -> StatusCode { pub async fn join(State(state): State<AppState>, Json(payload): Json<proto::JoinRequest>) -> StatusCode {
info!(target: "SESSION", "[JOIN] called with {:?}", payload);
let user = entities::user::Entity::find().filter( let user = entities::user::Entity::find().filter(
entities::user::Column::Uuid.eq(payload.selectedProfile) entities::user::Column::Uuid.eq(payload.selectedProfile)
).one(&state.db).await.unwrap().unwrap(); ).one(&state.db).await.unwrap().unwrap();
@ -31,6 +32,7 @@ pub async fn join(State(state): State<AppState>, Json(payload): Json<proto::Join
pub async fn has_joined(State(state): State<AppState>, Query(query): Query<HashMap<String, String>>) -> Result<Json<proto::JoinResponse>, StatusCode> { pub async fn has_joined(State(state): State<AppState>, Query(query): Query<HashMap<String, String>>) -> Result<Json<proto::JoinResponse>, StatusCode> {
let username = query.get("username").unwrap().clone(); let username = query.get("username").unwrap().clone();
let server_id = query.get("serverId").unwrap(); let server_id = query.get("serverId").unwrap();
info!(target: "SESSION", "[HAS_JOINED] called with user:{} server:{}", username, server_id);
let user = entities::user::Entity::find().filter( let user = entities::user::Entity::find().filter(
entities::user::Column::Name.eq(username.clone()) entities::user::Column::Name.eq(username.clone())
@ -45,29 +47,23 @@ pub async fn has_joined(State(state): State<AppState>, Query(query): Query<HashM
let response = proto::JoinResponse { let response = proto::JoinResponse {
id: user.uuid, id: user.uuid,
name: username.clone(), name: username.clone(),
properties: vec![ properties: vec![ proto::Property::default_skin() ],
proto::Property {
name: "textures".into(),
value: "".into(),
signature: Some("".into()),
}
],
}; };
info!(target: "hasJOINED", "server found user -> {:?}", response); info!(target: "SESSION", "[HAS_JOINED] server found user -> {:?}", response);
Ok(Json(response)) Ok(Json(response))
} else { } else {
warn!(target: "hasJOINED", "server found user but join was late or for another server"); warn!(target: "SESSION", "[HAS_JOINED] server found user but join was late or for another server");
Err(StatusCode::NOT_FOUND) Err(StatusCode::NOT_FOUND)
} }
}, },
None => { None => {
warn!(target: "hasJOINED", "server didn't find user"); warn!(target: "SESSION", "[HAS_JOINED] server didn't find user");
Err(StatusCode::NOT_FOUND) Err(StatusCode::NOT_FOUND)
}, },
} }
}, },
None => { None => {
warn!(target: "hasJOINED", "invalid UUID"); warn!(target: "SESSION", "[HAS_JOINED] invalid UUID");
Err(StatusCode::NOT_FOUND) Err(StatusCode::NOT_FOUND)
}, },
} }
@ -82,7 +78,7 @@ pub async fn profile(State(state): State<AppState>, Path(user_id): Path<Uuid>) -
Ok(Json(proto::SessionUser { Ok(Json(proto::SessionUser {
id: u.uuid, id: u.uuid,
name: u.name, name: u.name,
properties: Some(vec![]), properties: Some(vec![ proto::Property::default_skin() ]),
})) }))
} else { } else {
Err(StatusCode::NOT_FOUND) Err(StatusCode::NOT_FOUND)