Follow Rust and crates update
This commit is contained in:
@@ -86,14 +86,18 @@ impl<'a, 'r> FromRequest<'a, 'r> for ApiToken {
|
||||
}
|
||||
|
||||
let mut parsed_header = headers[0].split(' ');
|
||||
let auth_type = parsed_header.next().map_or_else(
|
||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoType)),
|
||||
Outcome::Success,
|
||||
)?;
|
||||
let val = parsed_header.next().map_or_else(
|
||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoValue)),
|
||||
Outcome::Success,
|
||||
)?;
|
||||
let auth_type = parsed_header
|
||||
.next()
|
||||
.map_or_else::<rocket::Outcome<&str, _, ()>, _, _>(
|
||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoType)),
|
||||
Outcome::Success,
|
||||
)?;
|
||||
let val = parsed_header
|
||||
.next()
|
||||
.map_or_else::<rocket::Outcome<&str, _, ()>, _, _>(
|
||||
|| Outcome::Failure((Status::BadRequest, TokenError::NoValue)),
|
||||
Outcome::Success,
|
||||
)?;
|
||||
|
||||
if auth_type == "Bearer" {
|
||||
let conn = request
|
||||
|
||||
@@ -28,7 +28,7 @@ impl BlocklistedEmail {
|
||||
pub fn delete_entries(conn: &Connection, ids: Vec<i32>) -> Result<bool> {
|
||||
use diesel::delete;
|
||||
for i in ids {
|
||||
let be: BlocklistedEmail = BlocklistedEmail::find_by_id(&conn, i)?;
|
||||
let be: BlocklistedEmail = BlocklistedEmail::find_by_id(conn, i)?;
|
||||
delete(&be).execute(conn)?;
|
||||
}
|
||||
Ok(true)
|
||||
|
||||
@@ -149,7 +149,15 @@ impl Blog {
|
||||
.into_iter()
|
||||
.find(|l| l.mime_type == Some(String::from("application/activity+json")))
|
||||
.ok_or(Error::Webfinger)
|
||||
.and_then(|l| Blog::from_id(conn, &l.href?, None, CONFIG.proxy()).map_err(|(_, e)| e))
|
||||
.and_then(|l| {
|
||||
Blog::from_id(
|
||||
conn,
|
||||
&l.href.ok_or(Error::MissingApProperty)?,
|
||||
None,
|
||||
CONFIG.proxy(),
|
||||
)
|
||||
.map_err(|(_, e)| e)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn to_activity(&self, conn: &Connection) -> Result<CustomGroup> {
|
||||
@@ -236,7 +244,7 @@ impl Blog {
|
||||
(min, max): (i32, i32),
|
||||
) -> Result<ActivityStream<OrderedCollectionPage>> {
|
||||
let mut coll = OrderedCollectionPage::default();
|
||||
let acts = self.get_activity_page(&conn, (min, max));
|
||||
let acts = self.get_activity_page(conn, (min, max));
|
||||
//This still doesn't do anything because the outbox
|
||||
//doesn't do anything yet
|
||||
coll.collection_page_props.set_next_link(Id::new(&format!(
|
||||
@@ -265,7 +273,10 @@ impl Blog {
|
||||
|
||||
pub fn get_keypair(&self) -> Result<PKey<Private>> {
|
||||
PKey::from_rsa(Rsa::private_key_from_pem(
|
||||
self.private_key.clone()?.as_ref(),
|
||||
self.private_key
|
||||
.clone()
|
||||
.ok_or(Error::MissingApProperty)?
|
||||
.as_ref(),
|
||||
)?)
|
||||
.map_err(Error::from)
|
||||
}
|
||||
@@ -318,7 +329,7 @@ impl Blog {
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &Connection) -> Result<()> {
|
||||
for post in Post::get_for_blog(conn, &self)? {
|
||||
for post in Post::get_for_blog(conn, self)? {
|
||||
post.delete(conn)?;
|
||||
}
|
||||
diesel::delete(self)
|
||||
@@ -339,12 +350,12 @@ impl FromId<DbConn> for Blog {
|
||||
type Object = CustomGroup;
|
||||
|
||||
fn from_db(conn: &DbConn, id: &str) -> Result<Self> {
|
||||
Self::find_by_ap_url(&conn, id)
|
||||
Self::find_by_ap_url(conn, id)
|
||||
}
|
||||
|
||||
fn from_activity(conn: &DbConn, acct: CustomGroup) -> Result<Self> {
|
||||
let url = Url::parse(&acct.object.object_props.id_string()?)?;
|
||||
let inst = url.host_str()?;
|
||||
let inst = url.host_str().ok_or(Error::Url)?;
|
||||
let instance = Instance::find_by_domain(conn, inst).or_else(|_| {
|
||||
Instance::insert(
|
||||
conn,
|
||||
@@ -468,7 +479,7 @@ impl sign::Signer for Blog {
|
||||
let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref())?)?;
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &key)?;
|
||||
verifier.update(data.as_bytes())?;
|
||||
verifier.verify(&signature).map_err(Error::from)
|
||||
verifier.verify(signature).map_err(Error::from)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,18 +141,20 @@ impl Comment {
|
||||
}
|
||||
|
||||
pub fn create_activity(&self, conn: &DbConn) -> Result<Create> {
|
||||
let author = User::get(&conn, self.author_id)?;
|
||||
let author = User::get(conn, self.author_id)?;
|
||||
|
||||
let note = self.to_activity(conn)?;
|
||||
let mut act = Create::default();
|
||||
act.create_props.set_actor_link(author.into_id())?;
|
||||
act.create_props.set_object_object(note.clone())?;
|
||||
act.object_props
|
||||
.set_id_string(format!("{}/activity", self.ap_url.clone()?,))?;
|
||||
act.object_props.set_id_string(format!(
|
||||
"{}/activity",
|
||||
self.ap_url.clone().ok_or(Error::MissingApProperty)?,
|
||||
))?;
|
||||
act.object_props
|
||||
.set_to_link_vec(note.object_props.to_link_vec::<Id>()?)?;
|
||||
act.object_props
|
||||
.set_cc_link_vec(vec![Id::new(self.get_author(&conn)?.followers_endpoint)])?;
|
||||
.set_cc_link_vec(vec![Id::new(self.get_author(conn)?.followers_endpoint)])?;
|
||||
Ok(act)
|
||||
}
|
||||
|
||||
@@ -182,7 +184,9 @@ impl Comment {
|
||||
.set_actor_link(self.get_author(conn)?.into_id())?;
|
||||
|
||||
let mut tombstone = Tombstone::default();
|
||||
tombstone.object_props.set_id_string(self.ap_url.clone()?)?;
|
||||
tombstone
|
||||
.object_props
|
||||
.set_id_string(self.ap_url.clone().ok_or(Error::MissingApProperty)?)?;
|
||||
act.delete_props.set_object_object(tombstone)?;
|
||||
|
||||
act.object_props
|
||||
@@ -204,7 +208,13 @@ impl FromId<DbConn> for Comment {
|
||||
|
||||
fn from_activity(conn: &DbConn, note: Note) -> Result<Self> {
|
||||
let comm = {
|
||||
let previous_url = note.object_props.in_reply_to.as_ref()?.as_str()?;
|
||||
let previous_url = note
|
||||
.object_props
|
||||
.in_reply_to
|
||||
.as_ref()
|
||||
.ok_or(Error::MissingApProperty)?
|
||||
.as_str()
|
||||
.ok_or(Error::MissingApProperty)?;
|
||||
let previous_comment = Comment::find_by_ap_url(conn, previous_url);
|
||||
|
||||
let is_public = |v: &Option<serde_json::Value>| match v
|
||||
@@ -346,7 +356,7 @@ impl AsObject<User, Delete, &DbConn> for Comment {
|
||||
m.delete(conn)?;
|
||||
}
|
||||
|
||||
for n in Notification::find_for_comment(&conn, &self)? {
|
||||
for n in Notification::find_for_comment(conn, &self)? {
|
||||
n.delete(&**conn)?;
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -17,7 +17,7 @@ pub struct Config {
|
||||
pub db_min_idle: Option<u32>,
|
||||
pub search_index: String,
|
||||
pub search_tokenizers: SearchTokenizerConfig,
|
||||
pub rocket: Result<RocketConfig, RocketError>,
|
||||
pub rocket: Result<RocketConfig, InvalidRocketConfig>,
|
||||
pub logo: LogoConfig,
|
||||
pub default_theme: String,
|
||||
pub media_directory: String,
|
||||
@@ -31,21 +31,21 @@ impl Config {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RocketError {
|
||||
InvalidEnv,
|
||||
InvalidAddress,
|
||||
InvalidSecretKey,
|
||||
pub enum InvalidRocketConfig {
|
||||
Env,
|
||||
Address,
|
||||
SecretKey,
|
||||
}
|
||||
|
||||
fn get_rocket_config() -> Result<RocketConfig, RocketError> {
|
||||
let mut c = RocketConfig::active().map_err(|_| RocketError::InvalidEnv)?;
|
||||
fn get_rocket_config() -> Result<RocketConfig, InvalidRocketConfig> {
|
||||
let mut c = RocketConfig::active().map_err(|_| InvalidRocketConfig::Env)?;
|
||||
|
||||
let address = var("ROCKET_ADDRESS").unwrap_or_else(|_| "localhost".to_owned());
|
||||
let port = var("ROCKET_PORT")
|
||||
.ok()
|
||||
.map(|s| s.parse::<u16>().unwrap())
|
||||
.unwrap_or(7878);
|
||||
let secret_key = var("ROCKET_SECRET_KEY").map_err(|_| RocketError::InvalidSecretKey)?;
|
||||
let secret_key = var("ROCKET_SECRET_KEY").map_err(|_| InvalidRocketConfig::SecretKey)?;
|
||||
let form_size = var("FORM_SIZE")
|
||||
.unwrap_or_else(|_| "128".to_owned())
|
||||
.parse::<u64>()
|
||||
@@ -56,10 +56,10 @@ fn get_rocket_config() -> Result<RocketConfig, RocketError> {
|
||||
.unwrap();
|
||||
|
||||
c.set_address(address)
|
||||
.map_err(|_| RocketError::InvalidAddress)?;
|
||||
.map_err(|_| InvalidRocketConfig::Address)?;
|
||||
c.set_port(port);
|
||||
c.set_secret_key(secret_key)
|
||||
.map_err(|_| RocketError::InvalidSecretKey)?;
|
||||
.map_err(|_| InvalidRocketConfig::SecretKey)?;
|
||||
|
||||
c.set_limits(
|
||||
Limits::new()
|
||||
@@ -155,7 +155,7 @@ impl Default for LogoConfig {
|
||||
.ok()
|
||||
.or_else(|| custom_main.clone());
|
||||
let other = if let Some(main) = custom_main.clone() {
|
||||
let ext = |path: &str| match path.rsplitn(2, '.').next() {
|
||||
let ext = |path: &str| match path.rsplit_once('.').map(|x| x.1) {
|
||||
Some("png") => Some("image/png".to_owned()),
|
||||
Some("jpg") | Some("jpeg") => Some("image/jpeg".to_owned()),
|
||||
Some("svg") => Some("image/svg+xml".to_owned()),
|
||||
|
||||
@@ -195,7 +195,7 @@ impl AsObject<User, Undo, &DbConn> for Follow {
|
||||
diesel::delete(&self).execute(&**conn)?;
|
||||
|
||||
// delete associated notification if any
|
||||
if let Ok(notif) = Notification::find(&conn, notification_kind::FOLLOW, self.id) {
|
||||
if let Ok(notif) = Notification::find(conn, notification_kind::FOLLOW, self.id) {
|
||||
diesel::delete(¬if).execute(&**conn)?;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#![feature(try_trait)]
|
||||
#![feature(never_type)]
|
||||
#![feature(proc_macro_hygiene)]
|
||||
#![feature(box_patterns)]
|
||||
@@ -86,12 +85,6 @@ impl From<diesel::result::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::option::NoneError> for Error {
|
||||
fn from(_: std::option::NoneError) -> Self {
|
||||
Error::NotFound
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for Error {
|
||||
fn from(_: url::ParseError) -> Self {
|
||||
Error::Url
|
||||
|
||||
@@ -148,7 +148,7 @@ impl AsObject<User, activity::Undo, &DbConn> for Like {
|
||||
diesel::delete(&self).execute(&**conn)?;
|
||||
|
||||
// delete associated notification if any
|
||||
if let Ok(notif) = Notification::find(&conn, notification_kind::LIKE, self.id) {
|
||||
if let Ok(notif) = Notification::find(conn, notification_kind::LIKE, self.id) {
|
||||
diesel::delete(¬if).execute(&**conn)?;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@@ -143,6 +143,7 @@ macro_rules! func {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Clone, Queryable, Identifiable)]
|
||||
struct ListElem {
|
||||
pub id: i32,
|
||||
|
||||
+24
-16
@@ -104,8 +104,8 @@ impl Media {
|
||||
pub fn category(&self) -> MediaCategory {
|
||||
match &*self
|
||||
.file_path
|
||||
.rsplitn(2, '.')
|
||||
.next()
|
||||
.rsplit_once('.')
|
||||
.map(|x| x.1)
|
||||
.expect("Media::category: extension error")
|
||||
.to_lowercase()
|
||||
{
|
||||
@@ -208,14 +208,17 @@ impl Media {
|
||||
|
||||
// TODO: merge with save_remote?
|
||||
pub fn from_activity(conn: &DbConn, image: &Image) -> Result<Media> {
|
||||
let remote_url = image.object_props.url_string().ok()?;
|
||||
let remote_url = image
|
||||
.object_props
|
||||
.url_string()
|
||||
.or(Err(Error::MissingApProperty))?;
|
||||
let path = determine_mirror_file_path(&remote_url);
|
||||
let parent = path.parent()?;
|
||||
let parent = path.parent().ok_or(Error::InvalidValue)?;
|
||||
if !parent.is_dir() {
|
||||
DirBuilder::new().recursive(true).create(parent)?;
|
||||
}
|
||||
|
||||
let mut dest = fs::File::create(path.clone()).ok()?;
|
||||
let mut dest = fs::File::create(path.clone())?;
|
||||
// TODO: conditional GET
|
||||
if let Some(proxy) = CONFIG.proxy() {
|
||||
reqwest::ClientBuilder::new().proxy(proxy.clone()).build()?
|
||||
@@ -223,16 +226,17 @@ impl Media {
|
||||
reqwest::Client::new()
|
||||
}
|
||||
.get(remote_url.as_str())
|
||||
.send()
|
||||
.ok()?
|
||||
.copy_to(&mut dest)
|
||||
.ok()?;
|
||||
.send()?
|
||||
.copy_to(&mut dest)?;
|
||||
|
||||
Media::find_by_file_path(conn, &path.to_str()?)
|
||||
Media::find_by_file_path(conn, path.to_str().ok_or(Error::InvalidValue)?)
|
||||
.and_then(|mut media| {
|
||||
let mut updated = false;
|
||||
|
||||
let alt_text = image.object_props.content_string().ok()?;
|
||||
let alt_text = image
|
||||
.object_props
|
||||
.content_string()
|
||||
.or(Err(Error::NotFound))?;
|
||||
let sensitive = image.object_props.summary_string().is_ok();
|
||||
let content_warning = image.object_props.summary_string().ok();
|
||||
if media.alt_text != alt_text {
|
||||
@@ -264,8 +268,11 @@ impl Media {
|
||||
Media::insert(
|
||||
conn,
|
||||
NewMedia {
|
||||
file_path: path.to_str()?.to_string(),
|
||||
alt_text: image.object_props.content_string().ok()?,
|
||||
file_path: path.to_str().ok_or(Error::InvalidValue)?.to_string(),
|
||||
alt_text: image
|
||||
.object_props
|
||||
.content_string()
|
||||
.or(Err(Error::NotFound))?,
|
||||
is_remote: false,
|
||||
remote_url: None,
|
||||
sensitive: image.object_props.summary_string().is_ok(),
|
||||
@@ -275,9 +282,10 @@ impl Media {
|
||||
image
|
||||
.object_props
|
||||
.attributed_to_link_vec::<Id>()
|
||||
.ok()?
|
||||
.or(Err(Error::NotFound))?
|
||||
.into_iter()
|
||||
.next()?
|
||||
.next()
|
||||
.ok_or(Error::NotFound)?
|
||||
.as_ref(),
|
||||
None,
|
||||
CONFIG.proxy(),
|
||||
@@ -325,7 +333,7 @@ fn determine_mirror_file_path(url: &str) -> PathBuf {
|
||||
.next()
|
||||
.map(ToOwned::to_owned)
|
||||
.unwrap_or_else(|| String::from("png"));
|
||||
file_path.push(format!("{}.{}", GUID::rand().to_string(), ext));
|
||||
file_path.push(format!("{}.{}", GUID::rand(), ext));
|
||||
});
|
||||
file_path
|
||||
}
|
||||
|
||||
@@ -47,7 +47,11 @@ impl Mention {
|
||||
|
||||
pub fn get_user(&self, conn: &Connection) -> Result<User> {
|
||||
match self.get_post(conn) {
|
||||
Ok(p) => Ok(p.get_authors(conn)?.into_iter().next()?),
|
||||
Ok(p) => Ok(p
|
||||
.get_authors(conn)?
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or(Error::NotFound)?),
|
||||
Err(_) => self.get_comment(conn).and_then(|c| c.get_author(conn)),
|
||||
}
|
||||
}
|
||||
@@ -77,7 +81,7 @@ impl Mention {
|
||||
in_post: bool,
|
||||
notify: bool,
|
||||
) -> Result<Self> {
|
||||
let ap_url = ment.link_props.href_string().ok()?;
|
||||
let ap_url = ment.link_props.href_string().or(Err(Error::NotFound))?;
|
||||
let mentioned = User::find_by_ap_url(conn, &ap_url)?;
|
||||
|
||||
if in_post {
|
||||
|
||||
@@ -105,7 +105,8 @@ impl ImportedMigrations {
|
||||
pub fn rerun_last_migration(&self, conn: &Connection, path: &Path) -> Result<()> {
|
||||
let latest_migration = conn.latest_run_migration_version()?;
|
||||
let id = latest_migration
|
||||
.and_then(|m| self.0.binary_search_by_key(&m.as_str(), |m| m.name).ok())?;
|
||||
.and_then(|m| self.0.binary_search_by_key(&m.as_str(), |m| m.name).ok())
|
||||
.ok_or(Error::NotFound)?;
|
||||
let migration = &self.0[id];
|
||||
conn.transaction(|| {
|
||||
migration.revert(conn, path)?;
|
||||
|
||||
@@ -61,7 +61,7 @@ impl PasswordResetRequest {
|
||||
}
|
||||
|
||||
pub fn find_and_delete_by_token(conn: &Connection, token: &str) -> Result<Self> {
|
||||
let request = Self::find_by_token(&conn, &token)?;
|
||||
let request = Self::find_by_token(conn, token)?;
|
||||
|
||||
let filter =
|
||||
password_reset_requests::table.filter(password_reset_requests::id.eq(request.id));
|
||||
|
||||
@@ -97,7 +97,7 @@ impl Post {
|
||||
}
|
||||
|
||||
pub fn delete(&self, conn: &Connection) -> Result<()> {
|
||||
for m in Mention::list_for_post(&conn, self.id)? {
|
||||
for m in Mention::list_for_post(conn, self.id)? {
|
||||
m.delete(conn)?;
|
||||
}
|
||||
diesel::delete(self).execute(conn)?;
|
||||
@@ -457,14 +457,14 @@ impl Post {
|
||||
.filter_map(|(id, m)| id.map(|id| (m, id)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let old_mentions = Mention::list_for_post(&conn, self.id)?;
|
||||
let old_mentions = Mention::list_for_post(conn, self.id)?;
|
||||
let old_user_mentioned = old_mentions
|
||||
.iter()
|
||||
.map(|m| m.mentioned_id)
|
||||
.collect::<HashSet<_>>();
|
||||
for (m, id) in &mentions {
|
||||
if !old_user_mentioned.contains(&id) {
|
||||
Mention::from_activity(&*conn, &m, self.id, true, true)?;
|
||||
if !old_user_mentioned.contains(id) {
|
||||
Mention::from_activity(&*conn, m, self.id, true, true)?;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ impl Post {
|
||||
.iter()
|
||||
.filter(|m| !new_mentions.contains(&m.mentioned_id))
|
||||
{
|
||||
m.delete(&conn)?;
|
||||
m.delete(conn)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -700,7 +700,7 @@ impl FromId<DbConn> for Post {
|
||||
Post::insert(
|
||||
conn,
|
||||
NewPost {
|
||||
blog_id: blog?.id,
|
||||
blog_id: blog.ok_or(Error::NotFound)?.id,
|
||||
slug: Self::slug(&title).to_string(),
|
||||
title,
|
||||
content: SafeString::new(&article.object_props.content_string()?),
|
||||
|
||||
@@ -173,7 +173,7 @@ impl AsObject<User, Undo, &DbConn> for Reshare {
|
||||
diesel::delete(&self).execute(&**conn)?;
|
||||
|
||||
// delete associated notification if any
|
||||
if let Ok(notif) = Notification::find(&conn, notification_kind::RESHARE, self.id) {
|
||||
if let Ok(notif) = Notification::find(conn, notification_kind::RESHARE, self.id) {
|
||||
diesel::delete(¬if).execute(&**conn)?;
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ pub struct SafeString {
|
||||
impl SafeString {
|
||||
pub fn new(value: &str) -> Self {
|
||||
SafeString {
|
||||
value: CLEAN.clean(&value).to_string(),
|
||||
value: CLEAN.clean(value).to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,7 @@ impl PlumeQuery {
|
||||
|
||||
/// Parse a query string into this Query
|
||||
pub fn parse_query(&mut self, query: &str) -> &mut Self {
|
||||
self.from_str_req(&query.trim())
|
||||
self.from_str_req(query.trim())
|
||||
}
|
||||
|
||||
/// Convert this Query to a Tantivy Query
|
||||
@@ -360,7 +360,7 @@ impl std::str::FromStr for PlumeQuery {
|
||||
fn from_str(query: &str) -> Result<PlumeQuery, !> {
|
||||
let mut res: PlumeQuery = Default::default();
|
||||
|
||||
res.from_str_req(&query.trim());
|
||||
res.from_str_req(query.trim());
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,6 @@ pub enum QueryError {
|
||||
RuntimeError(String),
|
||||
}
|
||||
|
||||
impl From<std::option::NoneError> for QueryError {
|
||||
fn from(_: std::option::NoneError) -> Self {
|
||||
QueryError::UnexpectedEndOfQuery
|
||||
}
|
||||
}
|
||||
|
||||
pub type QueryResult<T> = std::result::Result<T, QueryError>;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
@@ -239,7 +233,7 @@ impl WithList {
|
||||
) -> Result<bool> {
|
||||
match list {
|
||||
List::List(name) => {
|
||||
let list = lists::List::find_for_user_by_name(conn, timeline.user_id, &name)?;
|
||||
let list = lists::List::find_for_user_by_name(conn, timeline.user_id, name)?;
|
||||
match (self, list.kind()) {
|
||||
(WithList::Blog, ListType::Blog) => list.contains_blog(conn, post.blog_id),
|
||||
(WithList::Author { boosts, likes }, ListType::User) => match kind {
|
||||
@@ -414,7 +408,7 @@ enum List<'a> {
|
||||
|
||||
fn parse_s<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<'a>)> {
|
||||
let mut res = Vec::new();
|
||||
let (left, token) = parse_a(&stream)?;
|
||||
let (left, token) = parse_a(stream)?;
|
||||
res.push(token);
|
||||
stream = left;
|
||||
while !stream.is_empty() {
|
||||
@@ -436,7 +430,7 @@ fn parse_s<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>],
|
||||
|
||||
fn parse_a<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<'a>)> {
|
||||
let mut res = Vec::new();
|
||||
let (left, token) = parse_b(&stream)?;
|
||||
let (left, token) = parse_b(stream)?;
|
||||
res.push(token);
|
||||
stream = left;
|
||||
while !stream.is_empty() {
|
||||
@@ -463,7 +457,7 @@ fn parse_b<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<
|
||||
match left.get(0) {
|
||||
Some(Token::RParent(_)) => Ok((&left[1..], token)),
|
||||
Some(t) => t.get_error(Token::RParent(0)),
|
||||
None => None?,
|
||||
None => Err(QueryError::UnexpectedEndOfQuery),
|
||||
}
|
||||
}
|
||||
_ => parse_c(stream),
|
||||
@@ -484,9 +478,13 @@ fn parse_c<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], TQ<
|
||||
}
|
||||
|
||||
fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Arg<'a>)> {
|
||||
match stream.get(0).map(Token::get_text)? {
|
||||
match stream
|
||||
.get(0)
|
||||
.map(Token::get_text)
|
||||
.ok_or(QueryError::UnexpectedEndOfQuery)?
|
||||
{
|
||||
s @ "blog" | s @ "author" | s @ "license" | s @ "tags" | s @ "lang" => {
|
||||
match stream.get(1)? {
|
||||
match stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)? {
|
||||
Token::Word(_, _, r#in) if r#in == &"in" => {
|
||||
let (mut left, list) = parse_l(&stream[2..])?;
|
||||
let kind = match s {
|
||||
@@ -498,7 +496,12 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>],
|
||||
if *clude != "include" && *clude != "exclude" {
|
||||
break;
|
||||
}
|
||||
match (*clude, left.get(1).map(Token::get_text)?) {
|
||||
match (
|
||||
*clude,
|
||||
left.get(1)
|
||||
.map(Token::get_text)
|
||||
.ok_or(QueryError::UnexpectedEndOfQuery)?,
|
||||
) {
|
||||
("include", "reshares") | ("include", "reshare") => {
|
||||
boosts = true
|
||||
}
|
||||
@@ -529,7 +532,10 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>],
|
||||
t => t.get_error(Token::Word(0, 0, "'in'")),
|
||||
}
|
||||
}
|
||||
s @ "title" | s @ "subtitle" | s @ "content" => match (stream.get(1)?, stream.get(2)?) {
|
||||
s @ "title" | s @ "subtitle" | s @ "content" => match (
|
||||
stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)?,
|
||||
stream.get(2).ok_or(QueryError::UnexpectedEndOfQuery)?,
|
||||
) {
|
||||
(Token::Word(_, _, contains), Token::Word(_, _, w)) if contains == &"contains" => Ok((
|
||||
&stream[3..],
|
||||
Arg::Contains(
|
||||
@@ -555,7 +561,13 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>],
|
||||
if *clude != "include" && *clude != "exclude" {
|
||||
break;
|
||||
}
|
||||
match (*clude, stream.get(2).map(Token::get_text)?) {
|
||||
match (
|
||||
*clude,
|
||||
stream
|
||||
.get(2)
|
||||
.map(Token::get_text)
|
||||
.ok_or(QueryError::UnexpectedEndOfQuery)?,
|
||||
) {
|
||||
("include", "reshares") | ("include", "reshare") => boosts = true,
|
||||
("exclude", "reshares") | ("exclude", "reshare") => boosts = false,
|
||||
("include", "likes") | ("include", "like") => likes = true,
|
||||
@@ -577,20 +589,23 @@ fn parse_d<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>],
|
||||
"all" => Ok((&stream[1..], Arg::Boolean(Bool::All))),
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => stream.get(0)?.get_error(Token::Word(
|
||||
0,
|
||||
0,
|
||||
"one of 'blog', 'author', 'license', 'tags', 'lang', \
|
||||
_ => stream
|
||||
.get(0)
|
||||
.ok_or(QueryError::UnexpectedEndOfQuery)?
|
||||
.get_error(Token::Word(
|
||||
0,
|
||||
0,
|
||||
"one of 'blog', 'author', 'license', 'tags', 'lang', \
|
||||
'title', 'subtitle', 'content', 'followed', 'has_cover', 'local' or 'all'",
|
||||
)),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_l<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], List<'a>)> {
|
||||
match stream.get(0)? {
|
||||
match stream.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? {
|
||||
Token::LBracket(_) => {
|
||||
let (left, list) = parse_m(&stream[1..])?;
|
||||
match left.get(0)? {
|
||||
match left.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? {
|
||||
Token::RBracket(_) => Ok((&left[1..], List::Array(list))),
|
||||
t => t.get_error(Token::Word(0, 0, "one of ']' or ','")),
|
||||
}
|
||||
@@ -601,16 +616,20 @@ fn parse_l<'a, 'b>(stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Lis
|
||||
}
|
||||
|
||||
fn parse_m<'a, 'b>(mut stream: &'b [Token<'a>]) -> QueryResult<(&'b [Token<'a>], Vec<&'a str>)> {
|
||||
let mut res: Vec<&str> = vec![match stream.get(0)? {
|
||||
Token::Word(_, _, w) => w,
|
||||
t => return t.get_error(Token::Word(0, 0, "any word")),
|
||||
}];
|
||||
stream = &stream[1..];
|
||||
while let Token::Comma(_) = stream[0] {
|
||||
res.push(match stream.get(1)? {
|
||||
let mut res: Vec<&str> = vec![
|
||||
match stream.get(0).ok_or(QueryError::UnexpectedEndOfQuery)? {
|
||||
Token::Word(_, _, w) => w,
|
||||
t => return t.get_error(Token::Word(0, 0, "any word")),
|
||||
});
|
||||
},
|
||||
];
|
||||
stream = &stream[1..];
|
||||
while let Token::Comma(_) = stream[0] {
|
||||
res.push(
|
||||
match stream.get(1).ok_or(QueryError::UnexpectedEndOfQuery)? {
|
||||
Token::Word(_, _, w) => w,
|
||||
t => return t.get_error(Token::Word(0, 0, "any word")),
|
||||
},
|
||||
);
|
||||
stream = &stream[2..];
|
||||
}
|
||||
|
||||
|
||||
+16
-10
@@ -210,7 +210,13 @@ impl User {
|
||||
.into_iter()
|
||||
.find(|l| l.mime_type == Some(String::from("application/activity+json")))
|
||||
.ok_or(Error::Webfinger)?;
|
||||
User::from_id(conn, link.href.as_ref()?, None, CONFIG.proxy()).map_err(|(_, e)| e)
|
||||
User::from_id(
|
||||
conn,
|
||||
link.href.as_ref().ok_or(Error::Webfinger)?,
|
||||
None,
|
||||
CONFIG.proxy(),
|
||||
)
|
||||
.map_err(|(_, e)| e)
|
||||
}
|
||||
|
||||
pub fn fetch_remote_interact_uri(acct: &str) -> Result<String> {
|
||||
@@ -258,7 +264,7 @@ impl User {
|
||||
.icon_image()?
|
||||
.object_props
|
||||
.url_string()?,
|
||||
&self,
|
||||
self,
|
||||
)
|
||||
.ok();
|
||||
|
||||
@@ -427,12 +433,12 @@ impl User {
|
||||
let last = &format!(
|
||||
"{}?page={}",
|
||||
&self.outbox_url,
|
||||
self.get_activities_count(&conn) / i64::from(ITEMS_PER_PAGE) + 1
|
||||
self.get_activities_count(conn) / i64::from(ITEMS_PER_PAGE) + 1
|
||||
);
|
||||
coll.collection_props.set_first_link(Id::new(first))?;
|
||||
coll.collection_props.set_last_link(Id::new(last))?;
|
||||
coll.collection_props
|
||||
.set_total_items_u64(self.get_activities_count(&conn) as u64)?;
|
||||
.set_total_items_u64(self.get_activities_count(conn) as u64)?;
|
||||
Ok(ActivityStream::new(coll))
|
||||
}
|
||||
pub fn outbox_page(
|
||||
@@ -441,7 +447,7 @@ impl User {
|
||||
(min, max): (i32, i32),
|
||||
) -> Result<ActivityStream<OrderedCollectionPage>> {
|
||||
let acts = self.get_activities_page(conn, (min, max))?;
|
||||
let n_acts = self.get_activities_count(&conn);
|
||||
let n_acts = self.get_activities_count(conn);
|
||||
let mut coll = OrderedCollectionPage::default();
|
||||
if n_acts - i64::from(min) >= i64::from(ITEMS_PER_PAGE) {
|
||||
coll.collection_page_props.set_next_link(Id::new(&format!(
|
||||
@@ -513,7 +519,7 @@ impl User {
|
||||
if page.is_empty() {
|
||||
break;
|
||||
}
|
||||
items.extend(page.drain(..));
|
||||
items.append(&mut page);
|
||||
if let Some(n) = nxt {
|
||||
if n == next {
|
||||
break;
|
||||
@@ -720,7 +726,7 @@ impl User {
|
||||
|
||||
pub fn get_keypair(&self) -> Result<PKey<Private>> {
|
||||
PKey::from_rsa(Rsa::private_key_from_pem(
|
||||
self.private_key.clone()?.as_ref(),
|
||||
self.private_key.clone().ok_or(Error::Signature)?.as_ref(),
|
||||
)?)
|
||||
.map_err(Error::from)
|
||||
}
|
||||
@@ -943,7 +949,7 @@ impl FromId<DbConn> for User {
|
||||
|
||||
fn from_activity(conn: &DbConn, acct: CustomPerson) -> Result<Self> {
|
||||
let url = Url::parse(&acct.object.object_props.id_string()?)?;
|
||||
let inst = url.host_str()?;
|
||||
let inst = url.host_str().ok_or(Error::Url)?;
|
||||
let instance = Instance::find_by_domain(conn, inst).or_else(|_| {
|
||||
Instance::insert(
|
||||
conn,
|
||||
@@ -1080,7 +1086,7 @@ impl Signer for User {
|
||||
let key = PKey::from_rsa(Rsa::public_key_from_pem(self.public_key.as_ref())?)?;
|
||||
let mut verifier = sign::Verifier::new(MessageDigest::sha256(), &key)?;
|
||||
verifier.update(data.as_bytes())?;
|
||||
verifier.verify(&signature).map_err(Error::from)
|
||||
verifier.verify(signature).map_err(Error::from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1121,7 +1127,7 @@ impl NewUser {
|
||||
display_name,
|
||||
role: role as i32,
|
||||
summary: summary.to_owned(),
|
||||
summary_html: SafeString::new(&utils::md_to_html(&summary, None, false, None).0),
|
||||
summary_html: SafeString::new(&utils::md_to_html(summary, None, false, None).0),
|
||||
email: Some(email),
|
||||
hashed_password: password,
|
||||
instance_id: instance.id,
|
||||
|
||||
Reference in New Issue
Block a user