WIP - at a crossroads where we need some kind of auth mechanism
This commit is contained in:
parent
81c1ace175
commit
a867fdd831
|
@ -4,6 +4,7 @@ use rocket::response::status;
|
|||
use rocket::response::{self, Responder};
|
||||
use rocket_contrib::templates::Template;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::Into;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
@ -48,6 +49,28 @@ impl Error {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn message(&self) -> String {
|
||||
if self.is_sensitive() {
|
||||
"internal error".to_string()
|
||||
} else {
|
||||
self.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for tonic::Status {
|
||||
fn from(err: Error) -> tonic::Status {
|
||||
use tonic::{Code, Status};
|
||||
use Error::*;
|
||||
match err {
|
||||
NotFound => Status::new(Code::NotFound, err.message()),
|
||||
NotLoggedIn => Status::new(Code::Unauthenticated, err.message()),
|
||||
NoPermission => Status::new(Code::PermissionDenied, err.message()),
|
||||
InvalidInput => Status::new(Code::InvalidArgument, err.message()),
|
||||
_ => Status::new(Code::Internal, err.message()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[rocket::async_trait]
|
||||
|
|
89
src/grpc.rs
89
src/grpc.rs
|
@ -1,7 +1,66 @@
|
|||
use crate::models::proto::cofd::api::cofd_api_server::{CofdApi, CofdApiServer};
|
||||
use crate::db::Dao;
|
||||
use crate::errors::Error;
|
||||
use crate::models::characters::Character;
|
||||
use crate::models::proto::cofd::api::cofd_api_server::CofdApi;
|
||||
use crate::models::proto::cofd::api::UpdateSkillValueRequest;
|
||||
use crate::models::proto::cofd::cofd_sheet::Skill;
|
||||
use tonic::{transport::Server, Request, Response, Status};
|
||||
use crate::models::proto::cofd::*;
|
||||
use crate::models::users::User;
|
||||
use std::collections::btree_map::{Entry, OccupiedEntry};
|
||||
use tonic::{Request, Response, Status};
|
||||
|
||||
/// Load the character belonging to the given user, as long as they're
|
||||
/// the owner of that character. Returns an error if user is not
|
||||
/// logged in, the owner of the character is not found, or the logged
|
||||
/// in user does not have the permission to access this character.
|
||||
async fn load_character(
|
||||
conn: &sqlx::SqlitePool,
|
||||
logged_in_user: Option<&User>,
|
||||
owner: &str,
|
||||
character_id: i32,
|
||||
) -> Result<Character, Error> {
|
||||
let logged_in_user = logged_in_user.ok_or(Error::NotLoggedIn)?;
|
||||
|
||||
let character: Character = conn
|
||||
.load_character(character_id)
|
||||
.await?
|
||||
.ok_or(Error::NotFound)?;
|
||||
|
||||
if &logged_in_user.username != owner {
|
||||
return Err(Error::NoPermission);
|
||||
}
|
||||
|
||||
Ok(character)
|
||||
}
|
||||
|
||||
fn find_skill_entry<'a>(
|
||||
sheet: &'a mut CofdSheet,
|
||||
skill_name: &'a str,
|
||||
) -> Option<OccupiedEntry<'a, String, Skill>> {
|
||||
let all_skills = vec![
|
||||
&mut sheet.mental_skills,
|
||||
&mut sheet.physical_skills,
|
||||
&mut sheet.social_skills,
|
||||
];
|
||||
|
||||
// Search all skill lists for this value using "workaround" to
|
||||
// break value from for loops.
|
||||
let skill: Option<OccupiedEntry<_, _>> = 'l: loop {
|
||||
for skill_map in all_skills {
|
||||
if let Entry::Occupied(entry) = skill_map.entry(skill_name.to_owned()) {
|
||||
break 'l Some(entry);
|
||||
}
|
||||
}
|
||||
|
||||
break None;
|
||||
};
|
||||
|
||||
skill
|
||||
}
|
||||
|
||||
fn find_skill<'a>(sheet: &'a mut CofdSheet, skill_name: &'a str) -> Option<&'a mut Skill> {
|
||||
find_skill_entry(sheet, skill_name).map(|entry| entry.into_mut())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CofdApiService {
|
||||
|
@ -14,8 +73,30 @@ impl CofdApi for CofdApiService {
|
|||
&self,
|
||||
request: Request<UpdateSkillValueRequest>, // Accept request of type HelloRequest
|
||||
) -> Result<Response<Skill>, Status> {
|
||||
// Return an instance of type HelloReply
|
||||
println!("Got a request: {:?}", request);
|
||||
//Can use metadata map to add user id inside interceptor for auth.
|
||||
let request = request.into_inner();
|
||||
let mut character = load_character(
|
||||
&self.db,
|
||||
logged_in_user,
|
||||
&request.character_username,
|
||||
request.character_id,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut sheet: CofdSheet = character.try_deserialize()?;
|
||||
let skill: Option<&mut Skill> = find_skill(&mut sheet, &request.skill_name);
|
||||
|
||||
skill
|
||||
.map(|s| s.dots = request.skill_value)
|
||||
.ok_or(Error::InvalidInput)?;
|
||||
|
||||
println!("updated skill value",);
|
||||
|
||||
character.update_data(sheet)?;
|
||||
self.db
|
||||
.update_character_sheet(&character)
|
||||
.await
|
||||
.map_err(|e| e.into())?; //TODO maybe use crate Error for db
|
||||
|
||||
let reply = Skill::default();
|
||||
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
use crate::db::{Dao, TenebrousDbConn};
|
||||
use crate::errors::Error;
|
||||
use crate::models::characters::{Character, CharacterDataType, DynCharacterData, Visibility};
|
||||
use crate::models::characters::Character;
|
||||
use crate::models::proto::cofd::*;
|
||||
use crate::models::users::User;
|
||||
use rocket_contrib::templates::Template;
|
||||
use serde::Serialize;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::btree_map::{Entry, OccupiedEntry};
|
||||
|
||||
pub(crate) fn routes() -> Vec<rocket::Route> {
|
||||
|
|
Loading…
Reference in New Issue