Slash commands are cool
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

76 řádky
3.3KB

  1. use rocket::data::{self, FromDataSimple};
  2. use rocket::http::{Status};
  3. use rocket::{Request, Data, Outcome};
  4. use std::io::Read;
  5. use ed25519_dalek::{Verifier, Signature};
  6. use crate::discord::{Interaction, InteractionRaw};
  7. pub struct AuthenticatedInteraction {
  8. signature: String,
  9. timestamp: String,
  10. pub interaction: Interaction,
  11. }
  12. impl AuthenticatedInteraction {
  13. pub fn get_signature(&self) -> &str {
  14. &self.signature
  15. }
  16. pub fn get_timestamp(&self) -> &str {
  17. &self.timestamp
  18. }
  19. }
  20. impl FromDataSimple for AuthenticatedInteraction {
  21. type Error = ();
  22. fn from_data(request: &Request, data: Data) -> data::Outcome<Self, Self::Error> {
  23. let signature_opt = request.headers().get_one("x-signature-ed25519");
  24. let timestamp_opt = request.headers().get_one("x-signature-timestamp");
  25. if signature_opt.is_some() && timestamp_opt.is_some() {
  26. let signature = signature_opt.unwrap().to_owned();
  27. let timestamp = timestamp_opt.unwrap().to_owned();
  28. println!("signature: `{}` time: `{}`", &signature, &timestamp); // debug
  29. if let Ok(hex_data) = hex::decode(signature.clone()) {
  30. let mut buffer = [0; 64];
  31. for i in 0..64 { // copy hex decode into static-size buffer
  32. if i >= hex_data.len() { break; }
  33. buffer[i] = hex_data[i];
  34. }
  35. let sign = Signature::new(buffer); // requires [u8; 64]
  36. // validate authentication
  37. let mut string_buf = String::new();
  38. if let Ok(string_len) = data.open().take(1_000_000).read_to_string(&mut string_buf) {
  39. let msg = format!("{}{}", &timestamp, &string_buf[..string_len]);
  40. let verif_result = crate::VERIFICATION_KEY.read()
  41. .unwrap()
  42. .unwrap()
  43. .verify(msg.as_bytes(), &sign);
  44. if verif_result.is_err() {
  45. println!("Signature validation error");
  46. return Outcome::Failure((Status::Unauthorized, ()))
  47. }
  48. if let Ok(payload) = serde_json::from_str::<InteractionRaw>(&string_buf[..string_len]) {
  49. let auth = AuthenticatedInteraction {
  50. signature: signature.clone(),
  51. timestamp: timestamp.clone(),
  52. interaction: payload.interaction(),
  53. };
  54. if auth.interaction.is_invalid() {
  55. return Outcome::Failure((Status::BadRequest, ()));
  56. }
  57. return Outcome::Success(auth);
  58. }
  59. println!("Invalid json payload {}\n({})", &string_buf[..string_len], serde_json::from_str::<InteractionRaw>(&string_buf[..string_len]).err().unwrap());
  60. return Outcome::Failure((Status::Unauthorized, ()))
  61. }
  62. println!("Invalid body");
  63. return Outcome::Failure((Status::Unauthorized, ()))
  64. }
  65. println!("Invalid signature headers");
  66. return Outcome::Failure((Status::Unauthorized, ()))
  67. }
  68. println!("Missing signature headers");
  69. Outcome::Failure((Status::Unauthorized, ()))
  70. }
  71. }