Implement editing of attributes.
This commit is contained in:
parent
c0a48245b1
commit
4bff55cc6b
17
src/db.rs
17
src/db.rs
|
@ -13,16 +13,15 @@ pub(crate) trait Dao {
|
|||
|
||||
async fn load_user(&self, for_username: String) -> QueryResult<Option<User>>;
|
||||
|
||||
//async fn insert_user<'a>(&self, new_user: &'a NewUser<'a>) -> QueryResult<User>;
|
||||
|
||||
async fn insert_user(&self, new_user: NewUser) -> QueryResult<User>;
|
||||
|
||||
async fn load_character_list(&self, for_user_id: i32) -> QueryResult<Vec<StrippedCharacter>>;
|
||||
|
||||
async fn load_character(&self, character_id: i32) -> QueryResult<Option<Character>>;
|
||||
|
||||
//async fn insert_character<'a>(&self, new_character: NewCharacter<'a>) -> QueryResult<()>;
|
||||
async fn insert_character(&self, new_character: NewCharacter) -> QueryResult<()>;
|
||||
|
||||
async fn update_character_sheet(&self, character: Character) -> QueryResult<()>;
|
||||
}
|
||||
|
||||
type StrippedCharacterColumns = (
|
||||
|
@ -107,4 +106,16 @@ impl Dao for TenebrousDbConn {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn update_character_sheet(&self, character: Character) -> QueryResult<()> {
|
||||
use crate::schema::characters::dsl::*;
|
||||
self.run(move |conn| {
|
||||
diesel::update(&character)
|
||||
.set(data.eq(&character.data))
|
||||
.execute(conn)
|
||||
})
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ pub enum Error {
|
|||
#[error("you do not have permission to access this")]
|
||||
NoPermission,
|
||||
|
||||
#[error("invalid input")]
|
||||
InvalidInput,
|
||||
|
||||
#[error("query error: {0}")]
|
||||
QueryError(#[from] diesel::result::Error),
|
||||
|
||||
|
@ -35,6 +38,7 @@ impl Error {
|
|||
use Error::*;
|
||||
match self {
|
||||
QueryError(_) => true,
|
||||
IoError(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ impl CharacterDataType {
|
|||
|
||||
/// An entry that appears in a user's character list. Properties are
|
||||
/// in order of table columns.
|
||||
#[derive(Serialize, Debug, Queryable)]
|
||||
#[derive(Serialize, Debug, Queryable, Identifiable, AsChangeset)]
|
||||
pub struct Character {
|
||||
pub id: i32,
|
||||
pub user_id: i32,
|
||||
|
@ -129,8 +129,22 @@ impl Character {
|
|||
// fields.
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Update the existing character with new serialized protobuf
|
||||
/// data. Consumes the data.
|
||||
pub fn update_data<T>(&mut self, data: T) -> Result<(), Error>
|
||||
where
|
||||
T: prost::Message + std::default::Default,
|
||||
{
|
||||
let mut buf = BytesMut::with_capacity(std::mem::size_of_val(&data));
|
||||
data.encode(&mut buf)?;
|
||||
self.data = buf.to_vec();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Same as regular character type, but without the actual protobuf
|
||||
/// data loaded into memory.
|
||||
#[derive(Serialize, Debug, Queryable)]
|
||||
pub struct StrippedCharacter {
|
||||
pub id: i32,
|
||||
|
|
|
@ -41,15 +41,48 @@ mod cofd {
|
|||
"lol"
|
||||
}
|
||||
|
||||
#[post("/cofd/<owner>/<character_id>/attribute/<attribute>", data = "<info>")]
|
||||
pub(super) fn update_attribute<'a>(
|
||||
#[patch("/cofd/<owner>/<character_id>/attributes", data = "<attr_update>")]
|
||||
pub(super) async fn update_attribute<'a>(
|
||||
owner: String,
|
||||
character_id: i32,
|
||||
attribute: String,
|
||||
info: Proto<Attribute>,
|
||||
) -> &'a str {
|
||||
println!("incoming request is {:#?}", info);
|
||||
"lol"
|
||||
attr_update: Proto<Attribute>,
|
||||
conn: TenebrousDbConn,
|
||||
logged_in_user: Option<&User>,
|
||||
) -> Result<&'a str, Error> {
|
||||
let logged_in_user = logged_in_user.ok_or(Error::NotLoggedIn)?;
|
||||
let owner = conn.load_user(owner).await?.ok_or(Error::NotFound)?;
|
||||
let mut character: Character = conn
|
||||
.load_character(character_id)
|
||||
.await?
|
||||
.ok_or(Error::NotFound)?;
|
||||
|
||||
if logged_in_user != &owner {
|
||||
return Err(Error::NoPermission);
|
||||
}
|
||||
|
||||
let mut sheet: CofdSheet = character.try_deserialize()?;
|
||||
|
||||
match attr_update.name.to_lowercase().as_ref() {
|
||||
"strength" => Ok(sheet.strength += attr_update.value),
|
||||
"dexterity" => Ok(sheet.dexterity += attr_update.value),
|
||||
"stamina" => Ok(sheet.stamina += attr_update.value),
|
||||
"intelligence" => Ok(sheet.intelligence += attr_update.value),
|
||||
"wits" => Ok(sheet.wits += attr_update.value),
|
||||
"resolve" => Ok(sheet.resolve += attr_update.value),
|
||||
"presence" => Ok(sheet.presence += attr_update.value),
|
||||
"manipulation" => Ok(sheet.manipulation += attr_update.value),
|
||||
"composure" => Ok(sheet.composure += attr_update.value),
|
||||
_ => Err(Error::InvalidInput),
|
||||
}?;
|
||||
|
||||
println!(
|
||||
"updated {} attribute {} to {}",
|
||||
character.character_name, attr_update.name, attr_update.value
|
||||
);
|
||||
|
||||
character.update_data(sheet)?;
|
||||
conn.update_character_sheet(character).await?;
|
||||
Ok("lol")
|
||||
}
|
||||
|
||||
#[post("/cofd/<owner>/<character_id>/skills", data = "<info>")]
|
||||
|
@ -57,6 +90,7 @@ mod cofd {
|
|||
owner: String,
|
||||
character_id: i32,
|
||||
info: Proto<Skills>,
|
||||
conn: TenebrousDbConn,
|
||||
) -> &'a str {
|
||||
"lol"
|
||||
}
|
||||
|
|
|
@ -18,7 +18,8 @@ pub(crate) fn routes() -> Vec<rocket::Route> {
|
|||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ViewCharacterTemplate<'a> {
|
||||
struct ViewCharacterContext<'a> {
|
||||
pub id: i32,
|
||||
pub name: &'a str,
|
||||
pub username: &'a str,
|
||||
pub data_type: &'a CharacterDataType,
|
||||
|
@ -28,7 +29,8 @@ struct ViewCharacterTemplate<'a> {
|
|||
fn view_character_template(user: &User, character: Character) -> Result<Template, Error> {
|
||||
let character = character.uprade()?;
|
||||
|
||||
let context = ViewCharacterTemplate {
|
||||
let context = ViewCharacterContext {
|
||||
id: character.id,
|
||||
name: &character.character_name,
|
||||
username: &user.username,
|
||||
data_type: &character.data_type,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
function makeAPI(root) {
|
||||
const Attribute = root.lookupType("models.proto.cofd.api.Attribute");
|
||||
|
||||
const attributeResource = (username, characterID, attribute) =>
|
||||
'/api/cofd/' + username + '/' + characterID + '/attribute/' + attribute;
|
||||
const attributesResource = (username, characterID) =>
|
||||
'/api/cofd/' + username + '/' + characterID + '/attributes';
|
||||
|
||||
async function updateAttribute(params) {
|
||||
const { username, characterID, attribute, newValue } = params;
|
||||
|
@ -12,10 +12,10 @@ function makeAPI(root) {
|
|||
value: parseInt(newValue)
|
||||
});
|
||||
|
||||
const resource = attributeResource(username, characterID, attribute);
|
||||
const resource = attributesResource(username, characterID);
|
||||
|
||||
let resp = await fetch(resource, {
|
||||
method: 'POST',
|
||||
method: 'PATCH',
|
||||
body: Attribute.encode(req).finish()
|
||||
}).then(async resp => {
|
||||
console.log("resp is", await resp.text());
|
||||
|
|
|
@ -8,4 +8,8 @@
|
|||
<p>System: {{data_type}}</h3>
|
||||
<p>Strength: {{sheet.strength}}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="/characters/{{username}}/{{id}}/edit">Edit Character</a>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
Loading…
Reference in New Issue