Make media URLs in Mastodon API responses relative to current origin
This commit is contained in:
parent
c796cddff8
commit
e1e9851d5c
18 changed files with 204 additions and 33 deletions
|
@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
- Fixed actor object JSON-LD validation errors.
|
- Fixed actor object JSON-LD validation errors.
|
||||||
- Fixed activity JSON-LD validation errors.
|
- Fixed activity JSON-LD validation errors.
|
||||||
|
- Make media URLs in Mastodon API responses relative to current origin.
|
||||||
|
|
||||||
## [1.13.1] - 2023-02-09
|
## [1.13.1] - 2023-02-09
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,9 @@ pub fn get_hostname(url: &str) -> Result<String, ParseError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn guess_protocol(hostname: &str) -> &'static str {
|
pub fn guess_protocol(hostname: &str) -> &'static str {
|
||||||
|
if hostname == "localhost" {
|
||||||
|
return "http";
|
||||||
|
};
|
||||||
let maybe_ipv4_address = hostname.parse::<Ipv4Addr>();
|
let maybe_ipv4_address = hostname.parse::<Ipv4Addr>();
|
||||||
if let Ok(_ipv4_address) = maybe_ipv4_address {
|
if let Ok(_ipv4_address) = maybe_ipv4_address {
|
||||||
return "http";
|
return "http";
|
||||||
|
|
16
src/http.rs
16
src/http.rs
|
@ -1,6 +1,6 @@
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
body::{BodySize, BoxBody, MessageBody},
|
body::{BodySize, BoxBody, MessageBody},
|
||||||
dev::ServiceResponse,
|
dev::{ConnectionInfo, ServiceResponse},
|
||||||
error::{Error, JsonPayloadError},
|
error::{Error, JsonPayloadError},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
middleware::{ErrorHandlerResponse, ErrorHandlers},
|
middleware::{ErrorHandlerResponse, ErrorHandlers},
|
||||||
|
@ -10,6 +10,8 @@ use actix_web::{
|
||||||
};
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
|
use mitra_utils::urls::guess_protocol;
|
||||||
|
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
|
||||||
pub type FormOrJson<T> = Either<Form<T>, Json<T>>;
|
pub type FormOrJson<T> = Either<Form<T>, Json<T>>;
|
||||||
|
@ -46,3 +48,15 @@ pub fn json_error_handler(
|
||||||
other_error => other_error.into(),
|
other_error => other_error.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_request_base_url(connection_info: ConnectionInfo) -> String {
|
||||||
|
// TODO: HTTP server should set X-Forwarded-Proto header
|
||||||
|
// let scheme = connection_info.scheme();
|
||||||
|
let host = connection_info.host();
|
||||||
|
let scheme = if let Some((hostname, _port)) = host.split_once(':') {
|
||||||
|
guess_protocol(hostname)
|
||||||
|
} else {
|
||||||
|
guess_protocol(host)
|
||||||
|
};
|
||||||
|
format!("{}://{}", scheme, host)
|
||||||
|
}
|
||||||
|
|
|
@ -117,14 +117,15 @@ pub struct Account {
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
pub fn from_profile(
|
pub fn from_profile(
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
profile: DbActorProfile,
|
profile: DbActorProfile,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let profile_url = profile.actor_url(instance_url);
|
let profile_url = profile.actor_url(instance_url);
|
||||||
let avatar_url = profile.avatar
|
let avatar_url = profile.avatar
|
||||||
.map(|image| get_file_url(instance_url, &image.file_name));
|
.map(|image| get_file_url(base_url, &image.file_name));
|
||||||
let header_url = profile.banner
|
let header_url = profile.banner
|
||||||
.map(|image| get_file_url(instance_url, &image.file_name));
|
.map(|image| get_file_url(base_url, &image.file_name));
|
||||||
let is_locked = profile.actor_json
|
let is_locked = profile.actor_json
|
||||||
.map(|actor| actor.manually_approves_followers)
|
.map(|actor| actor.manually_approves_followers)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
@ -207,6 +208,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_user(
|
pub fn from_user(
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
user: User,
|
user: User,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -224,6 +226,7 @@ impl Account {
|
||||||
};
|
};
|
||||||
let role = ApiRole::from_db(user.role);
|
let role = ApiRole::from_db(user.role);
|
||||||
let mut account = Self::from_profile(
|
let mut account = Self::from_profile(
|
||||||
|
base_url,
|
||||||
instance_url,
|
instance_url,
|
||||||
user.profile,
|
user.profile,
|
||||||
);
|
);
|
||||||
|
@ -502,10 +505,12 @@ pub struct ApiSubscription {
|
||||||
|
|
||||||
impl ApiSubscription {
|
impl ApiSubscription {
|
||||||
pub fn from_subscription(
|
pub fn from_subscription(
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
subscription: Subscription,
|
subscription: Subscription,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let sender = Account::from_profile(
|
let sender = Account::from_profile(
|
||||||
|
base_url,
|
||||||
instance_url,
|
instance_url,
|
||||||
subscription.sender,
|
subscription.sender,
|
||||||
);
|
);
|
||||||
|
@ -545,6 +550,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let account = Account::from_profile(
|
let account = Account::from_profile(
|
||||||
|
INSTANCE_URL,
|
||||||
INSTANCE_URL,
|
INSTANCE_URL,
|
||||||
profile,
|
profile,
|
||||||
);
|
);
|
||||||
|
@ -570,6 +576,7 @@ mod tests {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
INSTANCE_URL,
|
||||||
INSTANCE_URL,
|
INSTANCE_URL,
|
||||||
user,
|
user,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
get, patch, post, web,
|
dev::ConnectionInfo,
|
||||||
HttpRequest, HttpResponse, Scope,
|
get,
|
||||||
|
patch,
|
||||||
|
post,
|
||||||
|
web,
|
||||||
|
HttpRequest,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
};
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -33,6 +39,7 @@ use crate::ethereum::{
|
||||||
gate::is_allowed_user,
|
gate::is_allowed_user,
|
||||||
identity::verify_eip191_identity_proof,
|
identity::verify_eip191_identity_proof,
|
||||||
};
|
};
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::identity::{
|
use crate::identity::{
|
||||||
claims::create_identity_claim,
|
claims::create_identity_claim,
|
||||||
did::Did,
|
did::Did,
|
||||||
|
@ -110,6 +117,7 @@ use super::types::{
|
||||||
|
|
||||||
#[post("")]
|
#[post("")]
|
||||||
pub async fn create_account(
|
pub async fn create_account(
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
maybe_blockchain: web::Data<Option<ContractSet>>,
|
maybe_blockchain: web::Data<Option<ContractSet>>,
|
||||||
|
@ -195,6 +203,7 @@ pub async fn create_account(
|
||||||
};
|
};
|
||||||
log::warn!("created user {}", user.id);
|
log::warn!("created user {}", user.id);
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
user,
|
user,
|
||||||
);
|
);
|
||||||
|
@ -204,12 +213,14 @@ pub async fn create_account(
|
||||||
#[get("/verify_credentials")]
|
#[get("/verify_credentials")]
|
||||||
async fn verify_credentials(
|
async fn verify_credentials(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let user = get_current_user(db_client, auth.token()).await?;
|
let user = get_current_user(db_client, auth.token()).await?;
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
user,
|
user,
|
||||||
);
|
);
|
||||||
|
@ -219,6 +230,7 @@ async fn verify_credentials(
|
||||||
#[patch("/update_credentials")]
|
#[patch("/update_credentials")]
|
||||||
async fn update_credentials(
|
async fn update_credentials(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_data: web::Json<AccountUpdateData>,
|
account_data: web::Json<AccountUpdateData>,
|
||||||
|
@ -246,6 +258,7 @@ async fn update_credentials(
|
||||||
).await?.enqueue(db_client).await?;
|
).await?.enqueue(db_client).await?;
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
@ -278,6 +291,7 @@ async fn get_unsigned_update(
|
||||||
#[post("/send_activity")]
|
#[post("/send_activity")]
|
||||||
async fn send_signed_activity(
|
async fn send_signed_activity(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
data: web::Json<SignedActivity>,
|
data: web::Json<SignedActivity>,
|
||||||
|
@ -323,6 +337,7 @@ async fn send_signed_activity(
|
||||||
outgoing_activity.enqueue(db_client).await?;
|
outgoing_activity.enqueue(db_client).await?;
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
@ -363,6 +378,7 @@ async fn get_identity_claim(
|
||||||
#[post("/identity_proof")]
|
#[post("/identity_proof")]
|
||||||
async fn create_identity_proof(
|
async fn create_identity_proof(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
proof_data: web::Json<IdentityProofData>,
|
proof_data: web::Json<IdentityProofData>,
|
||||||
|
@ -441,6 +457,7 @@ async fn create_identity_proof(
|
||||||
).await?.enqueue(db_client).await?;
|
).await?.enqueue(db_client).await?;
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
@ -465,6 +482,7 @@ async fn get_relationships_view(
|
||||||
|
|
||||||
#[get("/lookup")]
|
#[get("/lookup")]
|
||||||
async fn lookup_acct(
|
async fn lookup_acct(
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<LookupAcctQueryParams>,
|
query_params: web::Query<LookupAcctQueryParams>,
|
||||||
|
@ -472,6 +490,7 @@ async fn lookup_acct(
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let profile = get_profile_by_acct(db_client, &query_params.acct).await?;
|
let profile = get_profile_by_acct(db_client, &query_params.acct).await?;
|
||||||
let account = Account::from_profile(
|
let account = Account::from_profile(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
profile,
|
profile,
|
||||||
);
|
);
|
||||||
|
@ -480,6 +499,7 @@ async fn lookup_acct(
|
||||||
|
|
||||||
#[get("/search")]
|
#[get("/search")]
|
||||||
async fn search_by_acct(
|
async fn search_by_acct(
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<SearchAcctQueryParams>,
|
query_params: web::Query<SearchAcctQueryParams>,
|
||||||
|
@ -490,9 +510,11 @@ async fn search_by_acct(
|
||||||
&query_params.q,
|
&query_params.q,
|
||||||
query_params.limit.inner(),
|
query_params.limit.inner(),
|
||||||
).await?;
|
).await?;
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = profiles.into_iter()
|
let accounts: Vec<Account> = profiles.into_iter()
|
||||||
.map(|profile| Account::from_profile(
|
.map(|profile| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
profile,
|
profile,
|
||||||
))
|
))
|
||||||
|
@ -502,6 +524,7 @@ async fn search_by_acct(
|
||||||
|
|
||||||
#[get("/search_did")]
|
#[get("/search_did")]
|
||||||
async fn search_by_did(
|
async fn search_by_did(
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<SearchDidQueryParams>,
|
query_params: web::Query<SearchDidQueryParams>,
|
||||||
|
@ -510,9 +533,11 @@ async fn search_by_did(
|
||||||
let did: Did = query_params.did.parse()
|
let did: Did = query_params.did.parse()
|
||||||
.map_err(|_| ValidationError("invalid DID"))?;
|
.map_err(|_| ValidationError("invalid DID"))?;
|
||||||
let profiles = search_profiles_by_did(db_client, &did, false).await?;
|
let profiles = search_profiles_by_did(db_client, &did, false).await?;
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = profiles.into_iter()
|
let accounts: Vec<Account> = profiles.into_iter()
|
||||||
.map(|profile| Account::from_profile(
|
.map(|profile| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
profile,
|
profile,
|
||||||
))
|
))
|
||||||
|
@ -522,6 +547,7 @@ async fn search_by_did(
|
||||||
|
|
||||||
#[get("/{account_id}")]
|
#[get("/{account_id}")]
|
||||||
async fn get_account(
|
async fn get_account(
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_id: web::Path<Uuid>,
|
account_id: web::Path<Uuid>,
|
||||||
|
@ -529,6 +555,7 @@ async fn get_account(
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let profile = get_profile_by_id(db_client, &account_id).await?;
|
let profile = get_profile_by_id(db_client, &account_id).await?;
|
||||||
let account = Account::from_profile(
|
let account = Account::from_profile(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
profile,
|
profile,
|
||||||
);
|
);
|
||||||
|
@ -608,6 +635,7 @@ async fn unfollow_account(
|
||||||
#[get("/{account_id}/statuses")]
|
#[get("/{account_id}/statuses")]
|
||||||
async fn get_account_statuses(
|
async fn get_account_statuses(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_id: web::Path<Uuid>,
|
account_id: web::Path<Uuid>,
|
||||||
|
@ -636,6 +664,7 @@ async fn get_account_statuses(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
maybe_current_user.as_ref(),
|
maybe_current_user.as_ref(),
|
||||||
posts,
|
posts,
|
||||||
|
@ -646,6 +675,7 @@ async fn get_account_statuses(
|
||||||
#[get("/{account_id}/followers")]
|
#[get("/{account_id}/followers")]
|
||||||
async fn get_account_followers(
|
async fn get_account_followers(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_id: web::Path<Uuid>,
|
account_id: web::Path<Uuid>,
|
||||||
|
@ -668,9 +698,11 @@ async fn get_account_followers(
|
||||||
).await?;
|
).await?;
|
||||||
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
||||||
let maybe_last_id = followers.get(max_index).map(|item| item.relationship_id);
|
let maybe_last_id = followers.get(max_index).map(|item| item.relationship_id);
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = followers.into_iter()
|
let accounts: Vec<Account> = followers.into_iter()
|
||||||
.map(|item| Account::from_profile(
|
.map(|item| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
item.profile,
|
item.profile,
|
||||||
))
|
))
|
||||||
|
@ -687,6 +719,7 @@ async fn get_account_followers(
|
||||||
#[get("/{account_id}/following")]
|
#[get("/{account_id}/following")]
|
||||||
async fn get_account_following(
|
async fn get_account_following(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_id: web::Path<Uuid>,
|
account_id: web::Path<Uuid>,
|
||||||
|
@ -709,9 +742,11 @@ async fn get_account_following(
|
||||||
).await?;
|
).await?;
|
||||||
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
||||||
let maybe_last_id = following.get(max_index).map(|item| item.relationship_id);
|
let maybe_last_id = following.get(max_index).map(|item| item.relationship_id);
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = following.into_iter()
|
let accounts: Vec<Account> = following.into_iter()
|
||||||
.map(|item| Account::from_profile(
|
.map(|item| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
item.profile,
|
item.profile,
|
||||||
))
|
))
|
||||||
|
@ -728,6 +763,7 @@ async fn get_account_following(
|
||||||
#[get("/{account_id}/subscribers")]
|
#[get("/{account_id}/subscribers")]
|
||||||
async fn get_account_subscribers(
|
async fn get_account_subscribers(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
account_id: web::Path<Uuid>,
|
account_id: web::Path<Uuid>,
|
||||||
|
@ -741,6 +777,7 @@ async fn get_account_subscribers(
|
||||||
let subscriptions: Vec<ApiSubscription> = vec![];
|
let subscriptions: Vec<ApiSubscription> = vec![];
|
||||||
return Ok(HttpResponse::Ok().json(subscriptions));
|
return Ok(HttpResponse::Ok().json(subscriptions));
|
||||||
};
|
};
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance_url();
|
let instance_url = config.instance_url();
|
||||||
let subscriptions: Vec<ApiSubscription> = get_incoming_subscriptions(
|
let subscriptions: Vec<ApiSubscription> = get_incoming_subscriptions(
|
||||||
db_client,
|
db_client,
|
||||||
|
@ -751,6 +788,7 @@ async fn get_account_subscribers(
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|subscription| ApiSubscription::from_subscription(
|
.map(|subscription| ApiSubscription::from_subscription(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
subscription,
|
subscription,
|
||||||
))
|
))
|
||||||
|
|
|
@ -13,8 +13,8 @@ pub struct CustomEmoji {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CustomEmoji {
|
impl CustomEmoji {
|
||||||
pub fn from_db(instance_url: &str, emoji: DbEmoji) -> Self {
|
pub fn from_db(base_url: &str, emoji: DbEmoji) -> Self {
|
||||||
let image_url = get_file_url(instance_url, &emoji.image.file_name);
|
let image_url = get_file_url(base_url, &emoji.image.file_name);
|
||||||
Self {
|
Self {
|
||||||
shortcode: emoji.emoji_name,
|
shortcode: emoji.emoji_name,
|
||||||
url: image_url.clone(),
|
url: image_url.clone(),
|
||||||
|
|
|
@ -1,23 +1,28 @@
|
||||||
use actix_web::{get, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
use mitra_config::Config;
|
get,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::database::{get_database_client, DbPool};
|
use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::models::emojis::queries::get_local_emojis;
|
use crate::models::emojis::queries::get_local_emojis;
|
||||||
use super::types::CustomEmoji;
|
use super::types::CustomEmoji;
|
||||||
|
|
||||||
/// https://docs.joinmastodon.org/methods/custom_emojis/
|
/// https://docs.joinmastodon.org/methods/custom_emojis/
|
||||||
#[get("")]
|
#[get("")]
|
||||||
async fn custom_emoji_list(
|
async fn custom_emoji_list(
|
||||||
config: web::Data<Config>,
|
connection_info: ConnectionInfo,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let instance = config.instance();
|
let base_url = get_request_base_url(connection_info);
|
||||||
let emojis: Vec<CustomEmoji> = get_local_emojis(db_client).await?
|
let emojis: Vec<CustomEmoji> = get_local_emojis(db_client).await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|db_emoji| CustomEmoji::from_db(&instance.url(), db_emoji))
|
.map(|db_emoji| CustomEmoji::from_db(&base_url, db_emoji))
|
||||||
.collect();
|
.collect();
|
||||||
Ok(HttpResponse::Ok().json(emojis))
|
Ok(HttpResponse::Ok().json(emojis))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
/// https://docs.joinmastodon.org/methods/instance/directory/
|
/// https://docs.joinmastodon.org/methods/instance/directory/
|
||||||
use actix_web::{get, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
|
|
||||||
use crate::database::{get_database_client, DbPool};
|
use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
accounts::types::Account,
|
accounts::types::Account,
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
|
@ -16,6 +23,7 @@ use super::types::DirectoryQueryParams;
|
||||||
#[get("")]
|
#[get("")]
|
||||||
async fn profile_directory(
|
async fn profile_directory(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<DirectoryQueryParams>,
|
query_params: web::Query<DirectoryQueryParams>,
|
||||||
|
@ -28,10 +36,12 @@ async fn profile_directory(
|
||||||
query_params.offset,
|
query_params.offset,
|
||||||
query_params.limit.inner(),
|
query_params.limit.inner(),
|
||||||
).await?;
|
).await?;
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = profiles
|
let accounts: Vec<Account> = profiles
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|profile| Account::from_profile(
|
.map(|profile| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
profile,
|
profile,
|
||||||
))
|
))
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub struct Attachment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attachment {
|
impl Attachment {
|
||||||
pub fn from_db(instance_url: &str, db_attachment: DbMediaAttachment) -> Self {
|
pub fn from_db(base_url: &str, db_attachment: DbMediaAttachment) -> Self {
|
||||||
let attachment_type =
|
let attachment_type =
|
||||||
AttachmentType::from_media_type(db_attachment.media_type);
|
AttachmentType::from_media_type(db_attachment.media_type);
|
||||||
let attachment_type_mastodon = match attachment_type {
|
let attachment_type_mastodon = match attachment_type {
|
||||||
|
@ -35,7 +35,7 @@ impl Attachment {
|
||||||
AttachmentType::Video => "video",
|
AttachmentType::Video => "video",
|
||||||
};
|
};
|
||||||
let attachment_url = get_file_url(
|
let attachment_url = get_file_url(
|
||||||
instance_url,
|
base_url,
|
||||||
&db_attachment.file_name,
|
&db_attachment.file_name,
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -35,15 +35,17 @@ pub struct ApiNotification {
|
||||||
|
|
||||||
impl ApiNotification {
|
impl ApiNotification {
|
||||||
pub fn from_db(
|
pub fn from_db(
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
notification: Notification,
|
notification: Notification,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let account = Account::from_profile(
|
let account = Account::from_profile(
|
||||||
|
base_url,
|
||||||
instance_url,
|
instance_url,
|
||||||
notification.sender,
|
notification.sender,
|
||||||
);
|
);
|
||||||
let status = notification.post.map(|post| {
|
let status = notification.post.map(|post| {
|
||||||
Status::from_post(instance_url, post)
|
Status::from_post(base_url, instance_url, post)
|
||||||
});
|
});
|
||||||
let event_type_mastodon = match notification.event_type {
|
let event_type_mastodon = match notification.event_type {
|
||||||
EventType::Follow => "follow",
|
EventType::Follow => "follow",
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/// https://docs.joinmastodon.org/methods/notifications/
|
/// https://docs.joinmastodon.org/methods/notifications/
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
get, web,
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
web,
|
||||||
HttpRequest, HttpResponse,
|
HttpRequest, HttpResponse,
|
||||||
Scope as ActixScope,
|
Scope as ActixScope,
|
||||||
};
|
};
|
||||||
|
@ -10,6 +12,7 @@ use mitra_config::Config;
|
||||||
|
|
||||||
use crate::database::{get_database_client, DbPool};
|
use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
pagination::get_paginated_response,
|
pagination::get_paginated_response,
|
||||||
|
@ -20,6 +23,7 @@ use super::types::{ApiNotification, NotificationQueryParams};
|
||||||
#[get("")]
|
#[get("")]
|
||||||
async fn get_notifications_view(
|
async fn get_notifications_view(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<NotificationQueryParams>,
|
query_params: web::Query<NotificationQueryParams>,
|
||||||
|
@ -27,6 +31,8 @@ async fn get_notifications_view(
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
let db_client = &**get_database_client(&db_pool).await?;
|
let db_client = &**get_database_client(&db_pool).await?;
|
||||||
let current_user = get_current_user(db_client, auth.token()).await?;
|
let current_user = get_current_user(db_client, auth.token()).await?;
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
|
let instance = config.instance();
|
||||||
let notifications: Vec<ApiNotification> = get_notifications(
|
let notifications: Vec<ApiNotification> = get_notifications(
|
||||||
db_client,
|
db_client,
|
||||||
¤t_user.id,
|
¤t_user.id,
|
||||||
|
@ -34,13 +40,17 @@ async fn get_notifications_view(
|
||||||
query_params.limit.inner(),
|
query_params.limit.inner(),
|
||||||
).await?
|
).await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|item| ApiNotification::from_db(&config.instance_url(), item))
|
.map(|item| ApiNotification::from_db(
|
||||||
|
&base_url,
|
||||||
|
&instance.url(),
|
||||||
|
item,
|
||||||
|
))
|
||||||
.collect();
|
.collect();
|
||||||
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
let max_index = usize::from(query_params.limit.inner().saturating_sub(1));
|
||||||
let maybe_last_id = notifications.get(max_index)
|
let maybe_last_id = notifications.get(max_index)
|
||||||
.map(|item| item.id.clone());
|
.map(|item| item.id.clone());
|
||||||
let response = get_paginated_response(
|
let response = get_paginated_response(
|
||||||
&config.instance_url(),
|
&instance.url(),
|
||||||
request.uri().path(),
|
request.uri().path(),
|
||||||
notifications,
|
notifications,
|
||||||
maybe_last_id,
|
maybe_last_id,
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
/// https://docs.joinmastodon.org/methods/search/
|
/// https://docs.joinmastodon.org/methods/search/
|
||||||
use actix_web::{get, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
|
|
||||||
use crate::database::{get_database_client, DbPool};
|
use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
accounts::types::Account,
|
accounts::types::Account,
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
|
@ -18,6 +25,7 @@ use super::types::{SearchQueryParams, SearchResults};
|
||||||
#[get("")]
|
#[get("")]
|
||||||
async fn search_view(
|
async fn search_view(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<SearchQueryParams>,
|
query_params: web::Query<SearchQueryParams>,
|
||||||
|
@ -31,15 +39,18 @@ async fn search_view(
|
||||||
query_params.q.trim(),
|
query_params.q.trim(),
|
||||||
query_params.limit.inner(),
|
query_params.limit.inner(),
|
||||||
).await?;
|
).await?;
|
||||||
|
let base_url = get_request_base_url(connection_info);
|
||||||
let instance_url = config.instance().url();
|
let instance_url = config.instance().url();
|
||||||
let accounts: Vec<Account> = profiles.into_iter()
|
let accounts: Vec<Account> = profiles.into_iter()
|
||||||
.map(|profile| Account::from_profile(
|
.map(|profile| Account::from_profile(
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
profile,
|
profile,
|
||||||
))
|
))
|
||||||
.collect();
|
.collect();
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&base_url,
|
||||||
&instance_url,
|
&instance_url,
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
posts,
|
posts,
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
use actix_web::{get, post, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
|
@ -12,6 +19,7 @@ use crate::activitypub::{
|
||||||
};
|
};
|
||||||
use crate::database::{get_database_client, DatabaseError, DbPool};
|
use crate::database::{get_database_client, DatabaseError, DbPool};
|
||||||
use crate::errors::{HttpError, ValidationError};
|
use crate::errors::{HttpError, ValidationError};
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
accounts::types::Account,
|
accounts::types::Account,
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
|
@ -37,6 +45,7 @@ use super::types::{
|
||||||
#[post("/change_password")]
|
#[post("/change_password")]
|
||||||
async fn change_password_view(
|
async fn change_password_view(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
request_data: web::Json<PasswordChangeRequest>,
|
request_data: web::Json<PasswordChangeRequest>,
|
||||||
|
@ -47,6 +56,7 @@ async fn change_password_view(
|
||||||
.map_err(|_| HttpError::InternalError)?;
|
.map_err(|_| HttpError::InternalError)?;
|
||||||
set_user_password(db_client, ¤t_user.id, password_hash).await?;
|
set_user_password(db_client, ¤t_user.id, password_hash).await?;
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
@ -117,6 +127,7 @@ async fn import_follows_view(
|
||||||
#[post("/move_followers")]
|
#[post("/move_followers")]
|
||||||
async fn move_followers(
|
async fn move_followers(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
request_data: web::Json<MoveFollowersRequest>,
|
request_data: web::Json<MoveFollowersRequest>,
|
||||||
|
@ -194,6 +205,7 @@ async fn move_followers(
|
||||||
).enqueue(db_client).await?;
|
).enqueue(db_client).await?;
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&instance.url(),
|
&instance.url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
|
|
@ -75,6 +75,7 @@ pub async fn parse_microsyntaxes(
|
||||||
/// Load related objects and build status for API response
|
/// Load related objects and build status for API response
|
||||||
pub async fn build_status(
|
pub async fn build_status(
|
||||||
db_client: &impl DatabaseClient,
|
db_client: &impl DatabaseClient,
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
user: Option<&User>,
|
user: Option<&User>,
|
||||||
mut post: Post,
|
mut post: Post,
|
||||||
|
@ -83,12 +84,13 @@ pub async fn build_status(
|
||||||
if let Some(user) = user {
|
if let Some(user) = user {
|
||||||
add_user_actions(db_client, &user.id, vec![&mut post]).await?;
|
add_user_actions(db_client, &user.id, vec![&mut post]).await?;
|
||||||
};
|
};
|
||||||
let status = Status::from_post(instance_url, post);
|
let status = Status::from_post(base_url, instance_url, post);
|
||||||
Ok(status)
|
Ok(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn build_status_list(
|
pub async fn build_status_list(
|
||||||
db_client: &impl DatabaseClient,
|
db_client: &impl DatabaseClient,
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
user: Option<&User>,
|
user: Option<&User>,
|
||||||
mut posts: Vec<Post>,
|
mut posts: Vec<Post>,
|
||||||
|
@ -99,7 +101,7 @@ pub async fn build_status_list(
|
||||||
};
|
};
|
||||||
let statuses: Vec<Status> = posts
|
let statuses: Vec<Status> = posts
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|post| Status::from_post(instance_url, post))
|
.map(|post| Status::from_post(base_url, instance_url, post))
|
||||||
.collect();
|
.collect();
|
||||||
Ok(statuses)
|
Ok(statuses)
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,12 +85,13 @@ pub struct Status {
|
||||||
|
|
||||||
impl Status {
|
impl Status {
|
||||||
pub fn from_post(
|
pub fn from_post(
|
||||||
|
base_url: &str,
|
||||||
instance_url: &str,
|
instance_url: &str,
|
||||||
post: Post,
|
post: Post,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let object_id = post.object_id(instance_url);
|
let object_id = post.object_id(instance_url);
|
||||||
let attachments: Vec<Attachment> = post.attachments.into_iter()
|
let attachments: Vec<Attachment> = post.attachments.into_iter()
|
||||||
.map(|item| Attachment::from_db(instance_url, item))
|
.map(|item| Attachment::from_db(base_url, item))
|
||||||
.collect();
|
.collect();
|
||||||
let mentions: Vec<Mention> = post.mentions.into_iter()
|
let mentions: Vec<Mention> = post.mentions.into_iter()
|
||||||
.map(|item| Mention::from_profile(instance_url, item))
|
.map(|item| Mention::from_profile(instance_url, item))
|
||||||
|
@ -99,20 +100,21 @@ impl Status {
|
||||||
.map(|tag_name| Tag::from_tag_name(instance_url, tag_name))
|
.map(|tag_name| Tag::from_tag_name(instance_url, tag_name))
|
||||||
.collect();
|
.collect();
|
||||||
let emojis: Vec<CustomEmoji> = post.emojis.into_iter()
|
let emojis: Vec<CustomEmoji> = post.emojis.into_iter()
|
||||||
.map(|emoji| CustomEmoji::from_db(instance_url, emoji))
|
.map(|emoji| CustomEmoji::from_db(base_url, emoji))
|
||||||
.collect();
|
.collect();
|
||||||
let account = Account::from_profile(
|
let account = Account::from_profile(
|
||||||
|
base_url,
|
||||||
instance_url,
|
instance_url,
|
||||||
post.author,
|
post.author,
|
||||||
);
|
);
|
||||||
let reblog = if let Some(repost_of) = post.repost_of {
|
let reblog = if let Some(repost_of) = post.repost_of {
|
||||||
let status = Status::from_post(instance_url, *repost_of);
|
let status = Status::from_post(base_url, instance_url, *repost_of);
|
||||||
Some(Box::new(status))
|
Some(Box::new(status))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let links = post.linked.into_iter().map(|post| {
|
let links = post.linked.into_iter().map(|post| {
|
||||||
Status::from_post(instance_url, post)
|
Status::from_post(base_url, instance_url, post)
|
||||||
}).collect();
|
}).collect();
|
||||||
let visibility = match post.visibility {
|
let visibility = match post.visibility {
|
||||||
Visibility::Public => "public",
|
Visibility::Public => "public",
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
/// https://docs.joinmastodon.org/methods/statuses/
|
/// https://docs.joinmastodon.org/methods/statuses/
|
||||||
use actix_web::{delete, get, post, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
delete,
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
@ -21,7 +29,7 @@ use crate::activitypub::builders::{
|
||||||
use crate::database::{get_database_client, DatabaseError, DbPool};
|
use crate::database::{get_database_client, DatabaseError, DbPool};
|
||||||
use crate::errors::{HttpError, ValidationError};
|
use crate::errors::{HttpError, ValidationError};
|
||||||
use crate::ethereum::nft::create_mint_signature;
|
use crate::ethereum::nft::create_mint_signature;
|
||||||
use crate::http::FormOrJson;
|
use crate::http::{get_request_base_url, FormOrJson};
|
||||||
use crate::ipfs::{
|
use crate::ipfs::{
|
||||||
store as ipfs_store,
|
store as ipfs_store,
|
||||||
posts::PostMetadata,
|
posts::PostMetadata,
|
||||||
|
@ -69,6 +77,7 @@ use super::types::{
|
||||||
#[post("")]
|
#[post("")]
|
||||||
async fn create_status(
|
async fn create_status(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_data: FormOrJson<StatusData>,
|
status_data: FormOrJson<StatusData>,
|
||||||
|
@ -190,7 +199,11 @@ async fn create_status(
|
||||||
prepare_create_note(db_client, &instance, ¤t_user, &post)
|
prepare_create_note(db_client, &instance, ¤t_user, &post)
|
||||||
.await?.enqueue(db_client).await?;
|
.await?.enqueue(db_client).await?;
|
||||||
|
|
||||||
let status = Status::from_post(&instance.url(), post);
|
let status = Status::from_post(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
|
&instance.url(),
|
||||||
|
post,
|
||||||
|
);
|
||||||
Ok(HttpResponse::Ok().json(status))
|
Ok(HttpResponse::Ok().json(status))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,6 +245,7 @@ async fn preview_status(
|
||||||
#[get("/{status_id}")]
|
#[get("/{status_id}")]
|
||||||
async fn get_status(
|
async fn get_status(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -247,6 +261,7 @@ async fn get_status(
|
||||||
};
|
};
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
maybe_current_user.as_ref(),
|
maybe_current_user.as_ref(),
|
||||||
post,
|
post,
|
||||||
|
@ -285,6 +300,7 @@ async fn delete_status(
|
||||||
#[get("/{status_id}/context")]
|
#[get("/{status_id}/context")]
|
||||||
async fn get_context(
|
async fn get_context(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -301,6 +317,7 @@ async fn get_context(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
maybe_current_user.as_ref(),
|
maybe_current_user.as_ref(),
|
||||||
posts,
|
posts,
|
||||||
|
@ -327,6 +344,7 @@ async fn get_context(
|
||||||
async fn get_thread_view(
|
async fn get_thread_view(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
) -> Result<HttpResponse, HttpError> {
|
) -> Result<HttpResponse, HttpError> {
|
||||||
|
@ -342,6 +360,7 @@ async fn get_thread_view(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
maybe_current_user.as_ref(),
|
maybe_current_user.as_ref(),
|
||||||
posts,
|
posts,
|
||||||
|
@ -352,6 +371,7 @@ async fn get_thread_view(
|
||||||
#[post("/{status_id}/favourite")]
|
#[post("/{status_id}/favourite")]
|
||||||
async fn favourite(
|
async fn favourite(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -386,6 +406,7 @@ async fn favourite(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
post,
|
post,
|
||||||
|
@ -396,6 +417,7 @@ async fn favourite(
|
||||||
#[post("/{status_id}/unfavourite")]
|
#[post("/{status_id}/unfavourite")]
|
||||||
async fn unfavourite(
|
async fn unfavourite(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -427,6 +449,7 @@ async fn unfavourite(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
post,
|
post,
|
||||||
|
@ -437,6 +460,7 @@ async fn unfavourite(
|
||||||
#[post("/{status_id}/reblog")]
|
#[post("/{status_id}/reblog")]
|
||||||
async fn reblog(
|
async fn reblog(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -465,6 +489,7 @@ async fn reblog(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
repost,
|
repost,
|
||||||
|
@ -475,6 +500,7 @@ async fn reblog(
|
||||||
#[post("/{status_id}/unreblog")]
|
#[post("/{status_id}/unreblog")]
|
||||||
async fn unreblog(
|
async fn unreblog(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -502,6 +528,7 @@ async fn unreblog(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
post,
|
post,
|
||||||
|
@ -512,6 +539,7 @@ async fn unreblog(
|
||||||
#[post("/{status_id}/make_permanent")]
|
#[post("/{status_id}/make_permanent")]
|
||||||
async fn make_permanent(
|
async fn make_permanent(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -561,6 +589,7 @@ async fn make_permanent(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
post,
|
post,
|
||||||
|
@ -605,6 +634,7 @@ async fn get_signature(
|
||||||
#[post("/{status_id}/token_minted")]
|
#[post("/{status_id}/token_minted")]
|
||||||
async fn token_minted(
|
async fn token_minted(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
status_id: web::Path<Uuid>,
|
status_id: web::Path<Uuid>,
|
||||||
|
@ -625,6 +655,7 @@ async fn token_minted(
|
||||||
|
|
||||||
let status = build_status(
|
let status = build_status(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
post,
|
post,
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
use actix_web::{get, post, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
post,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -15,6 +22,7 @@ use crate::ethereum::{
|
||||||
is_registered_recipient,
|
is_registered_recipient,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
accounts::types::Account,
|
accounts::types::Account,
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
|
@ -92,6 +100,7 @@ async fn get_subscription_options(
|
||||||
#[post("/options")]
|
#[post("/options")]
|
||||||
pub async fn register_subscription_option(
|
pub async fn register_subscription_option(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
maybe_blockchain: web::Data<Option<ContractSet>>,
|
maybe_blockchain: web::Data<Option<ContractSet>>,
|
||||||
|
@ -166,6 +175,7 @@ pub async fn register_subscription_option(
|
||||||
};
|
};
|
||||||
|
|
||||||
let account = Account::from_user(
|
let account = Account::from_user(
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
current_user,
|
current_user,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
/// https://docs.joinmastodon.org/methods/timelines/
|
/// https://docs.joinmastodon.org/methods/timelines/
|
||||||
use actix_web::{get, web, HttpResponse, Scope};
|
use actix_web::{
|
||||||
|
dev::ConnectionInfo,
|
||||||
|
get,
|
||||||
|
web,
|
||||||
|
HttpResponse,
|
||||||
|
Scope,
|
||||||
|
};
|
||||||
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
use actix_web_httpauth::extractors::bearer::BearerAuth;
|
||||||
|
|
||||||
use mitra_config::Config;
|
use mitra_config::Config;
|
||||||
|
|
||||||
use crate::database::{get_database_client, DbPool};
|
use crate::database::{get_database_client, DbPool};
|
||||||
use crate::errors::HttpError;
|
use crate::errors::HttpError;
|
||||||
|
use crate::http::get_request_base_url;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
oauth::auth::get_current_user,
|
oauth::auth::get_current_user,
|
||||||
statuses::helpers::build_status_list,
|
statuses::helpers::build_status_list,
|
||||||
|
@ -20,6 +27,7 @@ use super::types::TimelineQueryParams;
|
||||||
#[get("/home")]
|
#[get("/home")]
|
||||||
async fn home_timeline(
|
async fn home_timeline(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<TimelineQueryParams>,
|
query_params: web::Query<TimelineQueryParams>,
|
||||||
|
@ -34,6 +42,7 @@ async fn home_timeline(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
posts,
|
posts,
|
||||||
|
@ -45,6 +54,7 @@ async fn home_timeline(
|
||||||
#[get("/public")]
|
#[get("/public")]
|
||||||
async fn public_timeline(
|
async fn public_timeline(
|
||||||
auth: BearerAuth,
|
auth: BearerAuth,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
query_params: web::Query<TimelineQueryParams>,
|
query_params: web::Query<TimelineQueryParams>,
|
||||||
|
@ -59,6 +69,7 @@ async fn public_timeline(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
Some(¤t_user),
|
Some(¤t_user),
|
||||||
posts,
|
posts,
|
||||||
|
@ -69,6 +80,7 @@ async fn public_timeline(
|
||||||
#[get("/tag/{hashtag}")]
|
#[get("/tag/{hashtag}")]
|
||||||
async fn hashtag_timeline(
|
async fn hashtag_timeline(
|
||||||
auth: Option<BearerAuth>,
|
auth: Option<BearerAuth>,
|
||||||
|
connection_info: ConnectionInfo,
|
||||||
config: web::Data<Config>,
|
config: web::Data<Config>,
|
||||||
db_pool: web::Data<DbPool>,
|
db_pool: web::Data<DbPool>,
|
||||||
hashtag: web::Path<String>,
|
hashtag: web::Path<String>,
|
||||||
|
@ -88,6 +100,7 @@ async fn hashtag_timeline(
|
||||||
).await?;
|
).await?;
|
||||||
let statuses = build_status_list(
|
let statuses = build_status_list(
|
||||||
db_client,
|
db_client,
|
||||||
|
&get_request_base_url(connection_info),
|
||||||
&config.instance_url(),
|
&config.instance_url(),
|
||||||
maybe_current_user.as_ref(),
|
maybe_current_user.as_ref(),
|
||||||
posts,
|
posts,
|
||||||
|
|
Loading…
Reference in a new issue