fix: insert new token, serve a default skin, log
This commit is contained in:
parent
0b19c94acf
commit
87e87811b3
3 changed files with 54 additions and 50 deletions
30
src/proto.rs
30
src/proto.rs
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue