Kibou is a federated social networking server.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

actor.rs 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. use database::models::{QueryActor};
  2. use database::schema::actors;
  3. use database::schema::actors::dsl::*;
  4. use diesel::ExpressionMethods;
  5. use diesel::pg::PgConnection;
  6. use diesel::query_dsl::QueryDsl;
  7. use diesel::query_dsl::RunQueryDsl;
  8. use diesel::sql_query;
  9. use openssl::hash::MessageDigest;
  10. use openssl::pkey::PKey;
  11. use openssl::rsa::Rsa;
  12. use openssl::sign::Signer;
  13. use pem::Pem;
  14. use serde_json;
  15. use url::Url;
  16. pub struct Actor
  17. {
  18. pub id: i64,
  19. pub email: Option<String>,
  20. pub password: Option<String>,
  21. pub actor_uri: String,
  22. pub username: Option<String>,
  23. pub preferred_username: String,
  24. pub summary: Option<String>,
  25. pub inbox: Option<String>,
  26. pub icon: Option<String>,
  27. pub local: bool,
  28. pub keys: serde_json::Value
  29. }
  30. impl Actor
  31. {
  32. /// Generates a new keypair and returns it as a serde_json::Value
  33. ///
  34. /// # Tests
  35. ///
  36. /// Tests for this function are in `tests/actor.rs`
  37. /// - generate_new_keys()
  38. fn generate_new_keys (&mut self) -> serde_json::Value
  39. {
  40. let rsa_keys = Rsa::generate(2048).unwrap();
  41. let public_key = Pem
  42. {
  43. tag: String::from("PUBLIC KEY"),
  44. contents: rsa_keys.public_key_to_der().unwrap()
  45. };
  46. let private_key = Pem
  47. {
  48. tag: String::from("PRIVATE KEY"),
  49. contents: rsa_keys.private_key_to_der().unwrap()
  50. };
  51. serde_json::json!({
  52. "public": pem::encode(&public_key),
  53. "private": pem::encode(&private_key)
  54. })
  55. }
  56. pub fn get_acct(&mut self) -> String
  57. {
  58. if self.local
  59. {
  60. self.preferred_username.to_string()
  61. }
  62. else
  63. {
  64. let url = Url::parse(&self.actor_uri).unwrap();
  65. format!("{username}@{host}", username=self.preferred_username, host=url.host_str().unwrap())
  66. }
  67. }
  68. pub fn get_public_key(&mut self) -> String
  69. {
  70. let parsed_public_key = self.keys["public"].as_str();
  71. parsed_public_key.unwrap().to_string()
  72. }
  73. pub fn get_private_key(&mut self) -> String
  74. {
  75. let parsed_private_key = self.keys["private"].as_str();
  76. parsed_private_key.unwrap().to_string()
  77. }
  78. /// Signs a string with the actor's private key and returns the newly signed string encoded in
  79. /// base64
  80. ///
  81. /// # Parameters
  82. ///
  83. /// * `request_string` - String | The string we want to get signed
  84. ///
  85. /// # Tests
  86. ///
  87. /// Tests for this function are in `tests/actor.rs`
  88. /// - sign()
  89. pub fn sign(&mut self, request_string: String) -> String
  90. {
  91. let private_key = self.get_private_key();
  92. let pem_decoded = pem::parse(private_key).unwrap();
  93. let pkey = PKey::from_rsa(openssl::rsa::Rsa::private_key_from_der(&pem_decoded.contents).unwrap()).unwrap();
  94. let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap();
  95. signer.update(&request_string.into_bytes()).unwrap();
  96. base64::encode(&signer.sign_to_vec().unwrap())
  97. }
  98. /// Updates the keypair of a local actor
  99. ///
  100. /// # Tests
  101. ///
  102. /// Tests for this function are in `tests/actor.rs`
  103. /// - update_local_keys()
  104. pub fn update_local_keys(&mut self)
  105. {
  106. self.keys = self.generate_new_keys();
  107. }
  108. }
  109. fn serialize_actor(sql_actor: QueryActor) -> Actor
  110. {
  111. Actor
  112. {
  113. id: sql_actor.id,
  114. email: sql_actor.email,
  115. password: sql_actor.password,
  116. actor_uri: sql_actor.actor_uri,
  117. username: sql_actor.username,
  118. preferred_username: sql_actor.preferred_username,
  119. summary: sql_actor.summary,
  120. inbox: sql_actor.inbox,
  121. icon: sql_actor.icon,
  122. keys: sql_actor.keys,
  123. local: sql_actor.local
  124. }
  125. }
  126. pub fn get_actor_by_acct(db_connection: &PgConnection, acct: String) -> Result<Actor, diesel::result::Error>
  127. {
  128. if acct.contains("@")
  129. {
  130. let acct_split = acct.split('@');
  131. let acct_vec = acct_split.collect::<Vec<&str>>();
  132. match sql_query(format!("SELECT * FROM actors WHERE preferred_username = '{username}' AND actor_uri LIKE '%{uri}/%' LIMIT 1;", username=acct_vec[0], uri=acct_vec[1]))
  133. .clone()
  134. .load::<QueryActor>(db_connection)
  135. {
  136. Ok(actor) => {
  137. if !actor.is_empty()
  138. {
  139. let new_actor = std::borrow::ToOwned::to_owned(&actor[0]);
  140. Ok(serialize_actor(new_actor))
  141. } else { Err(diesel::result::Error::NotFound) }
  142. },
  143. Err(e) => Err(e),
  144. }
  145. }
  146. else
  147. {
  148. get_local_actor_by_preferred_username(&db_connection, acct)
  149. }
  150. }
  151. pub fn get_actor_by_id(db_connection: &PgConnection, _id: i64) -> Result<Actor, diesel::result::Error>
  152. {
  153. match actors
  154. .filter(id.eq(_id))
  155. .limit(1)
  156. .first::<QueryActor>(db_connection)
  157. {
  158. Ok(actor) => Ok(serialize_actor(actor)),
  159. Err(e) => Err(e),
  160. }
  161. }
  162. pub fn get_actor_by_uri(db_connection: &PgConnection, _actor_uri: &str) -> Result<Actor, diesel::result::Error>
  163. {
  164. match actors
  165. .filter(actor_uri.eq(_actor_uri))
  166. .limit(1)
  167. .first::<QueryActor>(db_connection)
  168. {
  169. Ok(actor) => Ok(serialize_actor(actor)),
  170. Err(e) => Err(e),
  171. }
  172. }
  173. /// Runs a database query based on a local actor's preferred_username, returns either
  174. /// an actor::Actor or a diesel::result::Error
  175. ///
  176. /// # Parameters
  177. ///
  178. /// * `db_connection` - &PgConnection | Reference to a database connection
  179. /// * `preferred_username` - String | The preferred_username that is being queried
  180. ///
  181. /// # Tests
  182. ///
  183. /// Tests for this function are in `tests/actor.rs`
  184. /// - get_local_actor_by_preferred_username()
  185. pub fn get_local_actor_by_preferred_username(db_connection: &PgConnection, _preferred_username: String) -> Result<Actor, diesel::result::Error>
  186. {
  187. match actors
  188. .filter(preferred_username.eq(_preferred_username))
  189. .filter(local.eq(true))
  190. .limit(1)
  191. .first::<QueryActor>(db_connection)
  192. {
  193. Ok(actor) => Ok(serialize_actor(actor)),
  194. Err(e) => Err(e),
  195. }
  196. }
  197. /// Creates a new actor
  198. ///
  199. /// # Parameters
  200. ///
  201. /// * `db_connection` - &PgConnection | Reference to a database connection
  202. /// * `actor` - actor::Actor | An actor serialized in an actor::Actor struct
  203. ///
  204. /// # Tests
  205. ///
  206. /// Tests for this function are in `tests/actor.rs`
  207. /// - create_local_actor()
  208. /// - create_remote_actor()
  209. /// - create_actor_with_optional_values()
  210. pub fn create_actor (db_connection: &PgConnection, actor: &mut Actor)
  211. {
  212. if actor.local && actor.keys == serde_json::json!({})
  213. {
  214. actor.update_local_keys();
  215. }
  216. let new_actor = (email.eq(&actor.email),
  217. password.eq(&actor.password),
  218. actor_uri.eq(&actor.actor_uri),
  219. username.eq(&actor.username),
  220. preferred_username.eq(&actor.preferred_username),
  221. summary.eq(&actor.summary),
  222. inbox.eq(&actor.inbox),
  223. icon.eq(&actor.icon),
  224. local.eq(&actor.local),
  225. keys.eq(&actor.keys)
  226. );
  227. diesel::insert_into(actors::table)
  228. .values(new_actor)
  229. .execute(db_connection)
  230. .expect("Error creating user");
  231. }
  232. /// Deletes an actor base on their actor_uri
  233. ///
  234. /// # Parameters
  235. ///
  236. /// * `db_connection` - &PgConnection | Reference to a database connection
  237. /// * `actor` - actor::Actor | An actor serialized in an actor::Actor struct
  238. ///
  239. /// # Tests
  240. ///
  241. /// Tests for this function are at `tests/actor.rs`
  242. /// - delete_local_actor()
  243. /// - delete_remote_actor()
  244. pub fn delete (db_connection: &PgConnection, actor: &mut Actor)
  245. {
  246. diesel::delete(actors.filter(actor_uri.eq(&actor.actor_uri)))
  247. .execute(db_connection)
  248. .expect("Error deleting user");
  249. }